提交 2374e0f1 编写于 作者: A Alexei Starovoitov

Merge branch 'Improve BPF syscall command documentation'

Joe Stringer says:

====================

The state of bpf(2) manual pages today is not exactly ideal. For the
most part, it was written several years ago and has not kept up with the
pace of development in the kernel tree. For instance, out of a total of
~35 commands to the BPF syscall available today, when I pull the
kernel-man-pages tree today I find just 6 documented commands: The very
basics of map interaction and program load.

In contrast, looking at bpf-helpers(7), I am able today to run one
command[0] to fetch API documentation of the very latest eBPF helpers
that have been added to the kernel. This documentation is up to date
because kernel maintainers enforce documenting the APIs as part of
the feature submission process. As far as I can tell, we rely on manual
synchronization from the kernel tree to the kernel-man-pages tree to
distribute these more widely, so all locations may not be completely up
to date. That said, the documentation does in fact exist in the first
place which is a major initial hurdle to overcome.

Given the relative success of the process around bpf-helpers(7) to
encourage developers to document their user-facing changes, in this
patch series I explore applying this technique to bpf(2) as well.
Unfortunately, even with bpf(2) being so out-of-date, there is still a
lot of content to convert over. In particular, the following aspects of
the bpf syscall could also be individually be generated from separate
documentation in the header:
* BPF syscall commands
* BPF map types
* BPF program types
* BPF program subtypes (aka expected_attach_type)
* BPF attachment points

Rather than tackle everything at once, I have focused in this series on
the syscall commands, "enum bpf_cmd". This series is structured to first
import what useful descriptions there are from the kernel-man-pages
tree, then piece-by-piece document a few of the syscalls in more detail
in cases where I could find useful documentation from the git tree or
from a casual read of the code. Not all documentation is comprehensive
at this point, but a basis is provided with examples that can be further
enhanced with subsequent follow-up patches. Note, the series in its
current state only includes documentation around the syscall commands
themselves, so in the short term it doesn't allow us to automate bpf(2)
generation; Only one section of the man page could be replaced. Though
if there is appetite for this approach, this should be trivial to
improve on, even if just by importing the remaining static text from the
kernel-man-pages tree.

Following that, the series enhances the python scripting around parsing
the descriptions from the header files and generating dedicated
ReStructured Text and troff output. Finally, to expose the new text and
reduce the likelihood of having it get out of date or break the docs
parser, it is added to the selftests and exposed through the kernel
documentation web pages.

The eventual goal of this effort would be to extend the kernel UAPI
headers such that each of the categories I had listed above (commands,
maps, progs, hooks) have dedicated documentation in the kernel tree, and
that developers must update the comments in the headers to document the
APIs prior to patch acceptance, and that we could auto-generate the
latest version of the bpf(2) manual pages based on a few static
description sections combined with the dynamically-generated output from
the header.

This patch series can also be found at the following location on GitHub:
https://github.com/joestringer/linux/tree/submit/bpf-command-docs_v2

Thanks also to Quentin Monnet for initial review.

[0]: make -C tools/testing/selftests/bpf docs

v2:
* Remove build infrastructure in favor of kernel-doc directives
* Shift userspace-api docs under Documentation/userspace-api/ebpf
* Fix scripts/bpf_doc.py syscall --header (throw unsupported error)
* Improve .gitignore handling of newly autogenerated files

====================
Acked-by: NJonathan Corbet <corbet@lwn.net>
Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
...@@ -12,9 +12,6 @@ BPF instruction-set. ...@@ -12,9 +12,6 @@ BPF instruction-set.
The Cilium project also maintains a `BPF and XDP Reference Guide`_ The Cilium project also maintains a `BPF and XDP Reference Guide`_
that goes into great technical depth about the BPF Architecture. that goes into great technical depth about the BPF Architecture.
The primary info for the bpf syscall is available in the `man-pages`_
for `bpf(2)`_.
BPF Type Format (BTF) BPF Type Format (BTF)
===================== =====================
...@@ -35,6 +32,12 @@ Two sets of Questions and Answers (Q&A) are maintained. ...@@ -35,6 +32,12 @@ Two sets of Questions and Answers (Q&A) are maintained.
bpf_design_QA bpf_design_QA
bpf_devel_QA bpf_devel_QA
Syscall API
===========
The primary info for the bpf syscall is available in the `man-pages`_
for `bpf(2)`_. For more information about the userspace API, see
Documentation/userspace-api/ebpf/index.rst.
Helper functions Helper functions
================ ================
......
.. SPDX-License-Identifier: GPL-2.0
eBPF Userspace API
==================
eBPF is a kernel mechanism to provide a sandboxed runtime environment in the
Linux kernel for runtime extension and instrumentation without changing kernel
source code or loading kernel modules. eBPF programs can be attached to various
kernel subsystems, including networking, tracing and Linux security modules
(LSM).
For internal kernel documentation on eBPF, see Documentation/bpf/index.rst.
.. toctree::
:maxdepth: 1
syscall
.. SPDX-License-Identifier: GPL-2.0
eBPF Syscall
------------
:Authors: - Alexei Starovoitov <ast@kernel.org>
- Joe Stringer <joe@wand.net.nz>
- Michael Kerrisk <mtk.manpages@gmail.com>
The primary info for the bpf syscall is available in the `man-pages`_
for `bpf(2)`_.
bpf() subcommand reference
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: include/uapi/linux/bpf.h
:doc: eBPF Syscall Preamble
.. kernel-doc:: include/uapi/linux/bpf.h
:doc: eBPF Syscall Commands
.. Links:
.. _man-pages: https://www.kernel.org/doc/man-pages/
.. _bpf(2): https://man7.org/linux/man-pages/man2/bpf.2.html
...@@ -21,6 +21,7 @@ place where this information is gathered. ...@@ -21,6 +21,7 @@ place where this information is gathered.
unshare unshare
spec_ctrl spec_ctrl
accelerators/ocxl accelerators/ocxl
ebpf/index
ioctl/index ioctl/index
iommu iommu
media/index media/index
......
...@@ -3209,6 +3209,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git ...@@ -3209,6 +3209,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
F: Documentation/bpf/ F: Documentation/bpf/
F: Documentation/networking/filter.rst F: Documentation/networking/filter.rst
F: Documentation/userspace-api/ebpf/
F: arch/*/net/* F: arch/*/net/*
F: include/linux/bpf* F: include/linux/bpf*
F: include/linux/filter.h F: include/linux/filter.h
...@@ -3223,6 +3224,7 @@ F: net/core/filter.c ...@@ -3223,6 +3224,7 @@ F: net/core/filter.c
F: net/sched/act_bpf.c F: net/sched/act_bpf.c
F: net/sched/cls_bpf.c F: net/sched/cls_bpf.c
F: samples/bpf/ F: samples/bpf/
F: scripts/bpf_doc.py
F: tools/bpf/ F: tools/bpf/
F: tools/lib/bpf/ F: tools/lib/bpf/
F: tools/testing/selftests/bpf/ F: tools/testing/selftests/bpf/
......
此差异已折叠。
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
# #
# Copyright (C) 2018-2019 Netronome Systems, Inc. # Copyright (C) 2018-2019 Netronome Systems, Inc.
# Copyright (C) 2021 Isovalent, Inc.
# In case user attempts to run with Python 2. # In case user attempts to run with Python 2.
from __future__ import print_function from __future__ import print_function
...@@ -13,6 +14,9 @@ import sys, os ...@@ -13,6 +14,9 @@ import sys, os
class NoHelperFound(BaseException): class NoHelperFound(BaseException):
pass pass
class NoSyscallCommandFound(BaseException):
pass
class ParsingError(BaseException): class ParsingError(BaseException):
def __init__(self, line='<line not provided>', reader=None): def __init__(self, line='<line not provided>', reader=None):
if reader: if reader:
...@@ -22,18 +26,27 @@ class ParsingError(BaseException): ...@@ -22,18 +26,27 @@ class ParsingError(BaseException):
else: else:
BaseException.__init__(self, 'Error parsing line: %s' % line) BaseException.__init__(self, 'Error parsing line: %s' % line)
class Helper(object):
class APIElement(object):
""" """
An object representing the description of an eBPF helper function. An object representing the description of an aspect of the eBPF API.
@proto: function prototype of the helper function @proto: prototype of the API symbol
@desc: textual description of the helper function @desc: textual description of the symbol
@ret: description of the return value of the helper function @ret: (optional) description of any associated return value
""" """
def __init__(self, proto='', desc='', ret=''): def __init__(self, proto='', desc='', ret=''):
self.proto = proto self.proto = proto
self.desc = desc self.desc = desc
self.ret = ret self.ret = ret
class Helper(APIElement):
"""
An object representing the description of an eBPF helper function.
@proto: function prototype of the helper function
@desc: textual description of the helper function
@ret: description of the return value of the helper function
"""
def proto_break_down(self): def proto_break_down(self):
""" """
Break down helper function protocol into smaller chunks: return type, Break down helper function protocol into smaller chunks: return type,
...@@ -60,6 +73,7 @@ class Helper(object): ...@@ -60,6 +73,7 @@ class Helper(object):
return res return res
class HeaderParser(object): class HeaderParser(object):
""" """
An object used to parse a file in order to extract the documentation of a An object used to parse a file in order to extract the documentation of a
...@@ -72,6 +86,13 @@ class HeaderParser(object): ...@@ -72,6 +86,13 @@ class HeaderParser(object):
self.reader = open(filename, 'r') self.reader = open(filename, 'r')
self.line = '' self.line = ''
self.helpers = [] self.helpers = []
self.commands = []
def parse_element(self):
proto = self.parse_symbol()
desc = self.parse_desc()
ret = self.parse_ret()
return APIElement(proto=proto, desc=desc, ret=ret)
def parse_helper(self): def parse_helper(self):
proto = self.parse_proto() proto = self.parse_proto()
...@@ -79,6 +100,18 @@ class HeaderParser(object): ...@@ -79,6 +100,18 @@ class HeaderParser(object):
ret = self.parse_ret() ret = self.parse_ret()
return Helper(proto=proto, desc=desc, ret=ret) return Helper(proto=proto, desc=desc, ret=ret)
def parse_symbol(self):
p = re.compile(' \* ?(.+)$')
capture = p.match(self.line)
if not capture:
raise NoSyscallCommandFound
end_re = re.compile(' \* ?NOTES$')
end = end_re.match(self.line)
if end:
raise NoSyscallCommandFound
self.line = self.reader.readline()
return capture.group(1)
def parse_proto(self): def parse_proto(self):
# Argument can be of shape: # Argument can be of shape:
# - "void" # - "void"
...@@ -140,16 +173,29 @@ class HeaderParser(object): ...@@ -140,16 +173,29 @@ class HeaderParser(object):
break break
return ret return ret
def run(self): def seek_to(self, target, help_message):
# Advance to start of helper function descriptions. self.reader.seek(0)
offset = self.reader.read().find('* Start of BPF helper function descriptions:') offset = self.reader.read().find(target)
if offset == -1: if offset == -1:
raise Exception('Could not find start of eBPF helper descriptions list') raise Exception(help_message)
self.reader.seek(offset) self.reader.seek(offset)
self.reader.readline() self.reader.readline()
self.reader.readline() self.reader.readline()
self.line = self.reader.readline() self.line = self.reader.readline()
def parse_syscall(self):
self.seek_to('* DOC: eBPF Syscall Commands',
'Could not find start of eBPF syscall descriptions list')
while True:
try:
command = self.parse_element()
self.commands.append(command)
except NoSyscallCommandFound:
break
def parse_helpers(self):
self.seek_to('* Start of BPF helper function descriptions:',
'Could not find start of eBPF helper descriptions list')
while True: while True:
try: try:
helper = self.parse_helper() helper = self.parse_helper()
...@@ -157,6 +203,9 @@ class HeaderParser(object): ...@@ -157,6 +203,9 @@ class HeaderParser(object):
except NoHelperFound: except NoHelperFound:
break break
def run(self):
self.parse_syscall()
self.parse_helpers()
self.reader.close() self.reader.close()
############################################################################### ###############################################################################
...@@ -165,10 +214,11 @@ class Printer(object): ...@@ -165,10 +214,11 @@ class Printer(object):
""" """
A generic class for printers. Printers should be created with an array of A generic class for printers. Printers should be created with an array of
Helper objects, and implement a way to print them in the desired fashion. Helper objects, and implement a way to print them in the desired fashion.
@helpers: array of Helper objects to print to standard output @parser: A HeaderParser with objects to print to standard output
""" """
def __init__(self, helpers): def __init__(self, parser):
self.helpers = helpers self.parser = parser
self.elements = []
def print_header(self): def print_header(self):
pass pass
...@@ -181,19 +231,23 @@ class Printer(object): ...@@ -181,19 +231,23 @@ class Printer(object):
def print_all(self): def print_all(self):
self.print_header() self.print_header()
for helper in self.helpers: for elem in self.elements:
self.print_one(helper) self.print_one(elem)
self.print_footer() self.print_footer()
class PrinterRST(Printer): class PrinterRST(Printer):
""" """
A printer for dumping collected information about helpers as a ReStructured A generic class for printers that print ReStructured Text. Printers should
Text page compatible with the rst2man program, which can be used to be created with a HeaderParser object, and implement a way to print API
generate a manual page for the helpers. elements in the desired fashion.
@helpers: array of Helper objects to print to standard output @parser: A HeaderParser with objects to print to standard output
""" """
def print_header(self): def __init__(self, parser):
header = '''\ self.parser = parser
def print_license(self):
license = '''\
.. Copyright (C) All BPF authors and contributors from 2014 to present. .. Copyright (C) All BPF authors and contributors from 2014 to present.
.. See git log include/uapi/linux/bpf.h in kernel tree for details. .. See git log include/uapi/linux/bpf.h in kernel tree for details.
.. ..
...@@ -221,9 +275,39 @@ class PrinterRST(Printer): ...@@ -221,9 +275,39 @@ class PrinterRST(Printer):
.. ..
.. Please do not edit this file. It was generated from the documentation .. Please do not edit this file. It was generated from the documentation
.. located in file include/uapi/linux/bpf.h of the Linux kernel sources .. located in file include/uapi/linux/bpf.h of the Linux kernel sources
.. (helpers description), and from scripts/bpf_helpers_doc.py in the same .. (helpers description), and from scripts/bpf_doc.py in the same
.. repository (header and footer). .. repository (header and footer).
'''
print(license)
def print_elem(self, elem):
if (elem.desc):
print('\tDescription')
# Do not strip all newline characters: formatted code at the end of
# a section must be followed by a blank line.
for line in re.sub('\n$', '', elem.desc, count=1).split('\n'):
print('{}{}'.format('\t\t' if line else '', line))
if (elem.ret):
print('\tReturn')
for line in elem.ret.rstrip().split('\n'):
print('{}{}'.format('\t\t' if line else '', line))
print('')
class PrinterHelpersRST(PrinterRST):
"""
A printer for dumping collected information about helpers as a ReStructured
Text page compatible with the rst2man program, which can be used to
generate a manual page for the helpers.
@parser: A HeaderParser with Helper objects to print to standard output
"""
def __init__(self, parser):
self.elements = parser.helpers
def print_header(self):
header = '''\
=========== ===========
BPF-HELPERS BPF-HELPERS
=========== ===========
...@@ -264,6 +348,7 @@ kernel at the top). ...@@ -264,6 +348,7 @@ kernel at the top).
HELPERS HELPERS
======= =======
''' '''
PrinterRST.print_license(self)
print(header) print(header)
def print_footer(self): def print_footer(self):
...@@ -380,27 +465,50 @@ SEE ALSO ...@@ -380,27 +465,50 @@ SEE ALSO
def print_one(self, helper): def print_one(self, helper):
self.print_proto(helper) self.print_proto(helper)
self.print_elem(helper)
if (helper.desc):
print('\tDescription')
# Do not strip all newline characters: formatted code at the end of
# a section must be followed by a blank line.
for line in re.sub('\n$', '', helper.desc, count=1).split('\n'):
print('{}{}'.format('\t\t' if line else '', line))
if (helper.ret): class PrinterSyscallRST(PrinterRST):
print('\tReturn') """
for line in helper.ret.rstrip().split('\n'): A printer for dumping collected information about the syscall API as a
print('{}{}'.format('\t\t' if line else '', line)) ReStructured Text page compatible with the rst2man program, which can be
used to generate a manual page for the syscall.
@parser: A HeaderParser with APIElement objects to print to standard
output
"""
def __init__(self, parser):
self.elements = parser.commands
def print_header(self):
header = '''\
===
bpf
===
-------------------------------------------------------------------------------
Perform a command on an extended BPF object
-------------------------------------------------------------------------------
:Manual section: 2
COMMANDS
========
'''
PrinterRST.print_license(self)
print(header)
def print_one(self, command):
print('**%s**' % (command.proto))
self.print_elem(command)
print('')
class PrinterHelpers(Printer): class PrinterHelpers(Printer):
""" """
A printer for dumping collected information about helpers as C header to A printer for dumping collected information about helpers as C header to
be included from BPF program. be included from BPF program.
@helpers: array of Helper objects to print to standard output @parser: A HeaderParser with Helper objects to print to standard output
""" """
def __init__(self, parser):
self.elements = parser.helpers
type_fwds = [ type_fwds = [
'struct bpf_fib_lookup', 'struct bpf_fib_lookup',
...@@ -511,7 +619,7 @@ class PrinterHelpers(Printer): ...@@ -511,7 +619,7 @@ class PrinterHelpers(Printer):
def print_header(self): def print_header(self):
header = '''\ header = '''\
/* This is auto-generated file. See bpf_helpers_doc.py for details. */ /* This is auto-generated file. See bpf_doc.py for details. */
/* Forward declarations of BPF structs */''' /* Forward declarations of BPF structs */'''
...@@ -589,8 +697,13 @@ script = os.path.abspath(sys.argv[0]) ...@@ -589,8 +697,13 @@ script = os.path.abspath(sys.argv[0])
linuxRoot = os.path.dirname(os.path.dirname(script)) linuxRoot = os.path.dirname(os.path.dirname(script))
bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h') bpfh = os.path.join(linuxRoot, 'include/uapi/linux/bpf.h')
printers = {
'helpers': PrinterHelpersRST,
'syscall': PrinterSyscallRST,
}
argParser = argparse.ArgumentParser(description=""" argParser = argparse.ArgumentParser(description="""
Parse eBPF header file and generate documentation for eBPF helper functions. Parse eBPF header file and generate documentation for the eBPF API.
The RST-formatted output produced can be turned into a manual page with the The RST-formatted output produced can be turned into a manual page with the
rst2man utility. rst2man utility.
""") """)
...@@ -601,6 +714,8 @@ if (os.path.isfile(bpfh)): ...@@ -601,6 +714,8 @@ if (os.path.isfile(bpfh)):
default=bpfh) default=bpfh)
else: else:
argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h') argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h')
argParser.add_argument('target', nargs='?', default='helpers',
choices=printers.keys(), help='eBPF API target')
args = argParser.parse_args() args = argParser.parse_args()
# Parse file. # Parse file.
...@@ -609,7 +724,9 @@ headerParser.run() ...@@ -609,7 +724,9 @@ headerParser.run()
# Print formatted output to standard output. # Print formatted output to standard output.
if args.header: if args.header:
printer = PrinterHelpers(headerParser.helpers) if args.target != 'helpers':
raise NotImplementedError('Only helpers header generation is supported')
printer = PrinterHelpers(headerParser)
else: else:
printer = PrinterRST(headerParser.helpers) printer = printers[args.target](headerParser)
printer.print_all() printer.print_all()
# SPDX-License-Identifier: GPL-2.0-only
ifndef allow-override
include ../scripts/Makefile.include
include ../scripts/utilities.mak
else
# Assume Makefile.helpers is being run from bpftool/Documentation
# subdirectory. Go up two more directories to fetch bpf.h header and
# associated script.
UP2DIR := ../../
endif
INSTALL ?= install
RM ?= rm -f
RMDIR ?= rmdir --ignore-fail-on-non-empty
ifeq ($(V),1)
Q =
else
Q = @
endif
prefix ?= /usr/local
mandir ?= $(prefix)/man
man7dir = $(mandir)/man7
HELPERS_RST = bpf-helpers.rst
MAN7_RST = $(HELPERS_RST)
_DOC_MAN7 = $(patsubst %.rst,%.7,$(MAN7_RST))
DOC_MAN7 = $(addprefix $(OUTPUT),$(_DOC_MAN7))
helpers: man7
man7: $(DOC_MAN7)
RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null)
$(OUTPUT)$(HELPERS_RST): $(UP2DIR)../../include/uapi/linux/bpf.h
$(QUIET_GEN)$(UP2DIR)../../scripts/bpf_helpers_doc.py --filename $< > $@
$(OUTPUT)%.7: $(OUTPUT)%.rst
ifndef RST2MAN_DEP
$(error "rst2man not found, but required to generate man pages")
endif
$(QUIET_GEN)rst2man $< > $@
helpers-clean:
$(call QUIET_CLEAN, eBPF_helpers-manpage)
$(Q)$(RM) $(DOC_MAN7) $(OUTPUT)$(HELPERS_RST)
helpers-install: helpers
$(call QUIET_INSTALL, eBPF_helpers-manpage)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man7dir)
$(Q)$(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
helpers-uninstall:
$(call QUIET_UNINST, eBPF_helpers-manpage)
$(Q)$(RM) $(addprefix $(DESTDIR)$(man7dir)/,$(_DOC_MAN7))
$(Q)$(RMDIR) $(DESTDIR)$(man7dir)
.PHONY: helpers helpers-clean helpers-install helpers-uninstall
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
/bootstrap/ /bootstrap/
/bpftool /bpftool
bpftool*.8 bpftool*.8
bpf-helpers.*
FEATURE-DUMP.bpftool FEATURE-DUMP.bpftool
feature feature
libbpf libbpf
......
...@@ -16,15 +16,12 @@ prefix ?= /usr/local ...@@ -16,15 +16,12 @@ prefix ?= /usr/local
mandir ?= $(prefix)/man mandir ?= $(prefix)/man
man8dir = $(mandir)/man8 man8dir = $(mandir)/man8
# Load targets for building eBPF helpers man page.
include ../../Makefile.helpers
MAN8_RST = $(wildcard bpftool*.rst) MAN8_RST = $(wildcard bpftool*.rst)
_DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST)) _DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST))
DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8)) DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8))
man: man8 helpers man: man8
man8: $(DOC_MAN8) man8: $(DOC_MAN8)
RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null)
...@@ -46,16 +43,16 @@ ifndef RST2MAN_DEP ...@@ -46,16 +43,16 @@ ifndef RST2MAN_DEP
endif endif
$(QUIET_GEN)( cat $< ; printf "%b" $(call see_also,$<) ) | rst2man $(RST2MAN_OPTS) > $@ $(QUIET_GEN)( cat $< ; printf "%b" $(call see_also,$<) ) | rst2man $(RST2MAN_OPTS) > $@
clean: helpers-clean clean:
$(call QUIET_CLEAN, Documentation) $(call QUIET_CLEAN, Documentation)
$(Q)$(RM) $(DOC_MAN8) $(Q)$(RM) $(DOC_MAN8)
install: man helpers-install install: man
$(call QUIET_INSTALL, Documentation-man) $(call QUIET_INSTALL, Documentation-man)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir) $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir)
$(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir) $(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir)
uninstall: helpers-uninstall uninstall:
$(call QUIET_UNINST, Documentation-man) $(call QUIET_UNINST, Documentation-man)
$(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8)) $(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8))
$(Q)$(RMDIR) $(DESTDIR)$(man8dir) $(Q)$(RMDIR) $(DESTDIR)$(man8dir)
......
此差异已折叠。
...@@ -158,7 +158,7 @@ $(BPF_IN_STATIC): force $(BPF_HELPER_DEFS) ...@@ -158,7 +158,7 @@ $(BPF_IN_STATIC): force $(BPF_HELPER_DEFS)
$(Q)$(MAKE) $(build)=libbpf OUTPUT=$(STATIC_OBJDIR) $(Q)$(MAKE) $(build)=libbpf OUTPUT=$(STATIC_OBJDIR)
$(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h $(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h
$(QUIET_GEN)$(srctree)/scripts/bpf_helpers_doc.py --header \ $(QUIET_GEN)$(srctree)/scripts/bpf_doc.py --header \
--file $(srctree)/tools/include/uapi/linux/bpf.h > $(BPF_HELPER_DEFS) --file $(srctree)/tools/include/uapi/linux/bpf.h > $(BPF_HELPER_DEFS)
$(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION) $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)
......
...@@ -20,4 +20,4 @@ tools/lib/bitmap.c ...@@ -20,4 +20,4 @@ tools/lib/bitmap.c
tools/lib/str_error_r.c tools/lib/str_error_r.c
tools/lib/vsprintf.c tools/lib/vsprintf.c
tools/lib/zalloc.c tools/lib/zalloc.c
scripts/bpf_helpers_doc.py scripts/bpf_doc.py
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
bpf-helpers*
bpf-syscall*
test_verifier test_verifier
test_maps test_maps
test_lru_map test_lru_map
......
...@@ -68,6 +68,7 @@ TEST_PROGS := test_kmod.sh \ ...@@ -68,6 +68,7 @@ TEST_PROGS := test_kmod.sh \
test_bpftool_build.sh \ test_bpftool_build.sh \
test_bpftool.sh \ test_bpftool.sh \
test_bpftool_metadata.sh \ test_bpftool_metadata.sh \
test_docs_build.sh \
test_xsk.sh test_xsk.sh
TEST_PROGS_EXTENDED := with_addr.sh \ TEST_PROGS_EXTENDED := with_addr.sh \
...@@ -103,6 +104,7 @@ override define CLEAN ...@@ -103,6 +104,7 @@ override define CLEAN
$(call msg,CLEAN) $(call msg,CLEAN)
$(Q)$(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN) $(Q)$(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
$(Q)$(MAKE) -C bpf_testmod clean $(Q)$(MAKE) -C bpf_testmod clean
$(Q)$(MAKE) docs-clean
endef endef
include ../lib.mk include ../lib.mk
...@@ -180,6 +182,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) ...@@ -180,6 +182,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL)
cp $(SCRATCH_DIR)/runqslower $@ cp $(SCRATCH_DIR)/runqslower $@
$(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/test_stub.o $(BPFOBJ) $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED): $(OUTPUT)/test_stub.o $(BPFOBJ)
$(TEST_GEN_FILES): docs
$(OUTPUT)/test_dev_cgroup: cgroup_helpers.c $(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
$(OUTPUT)/test_skb_cgroup_id_user: cgroup_helpers.c $(OUTPUT)/test_skb_cgroup_id_user: cgroup_helpers.c
...@@ -200,11 +203,16 @@ $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ ...@@ -200,11 +203,16 @@ $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
CC=$(HOSTCC) LD=$(HOSTLD) \ CC=$(HOSTCC) LD=$(HOSTLD) \
OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
prefix= DESTDIR=$(HOST_SCRATCH_DIR)/ install prefix= DESTDIR=$(HOST_SCRATCH_DIR)/ install
$(Q)mkdir -p $(BUILD_DIR)/bpftool/Documentation
$(Q)RST2MAN_OPTS="--exit-status=1" $(MAKE) $(submake_extras) \ docs:
-C $(BPFTOOLDIR)/Documentation \ $(Q)RST2MAN_OPTS="--exit-status=1" $(MAKE) $(submake_extras) \
OUTPUT=$(BUILD_DIR)/bpftool/Documentation/ \ -f Makefile.docs \
prefix= DESTDIR=$(SCRATCH_DIR)/ install prefix= OUTPUT=$(OUTPUT)/ DESTDIR=$(OUTPUT)/ $@
docs-clean:
$(Q)$(MAKE) $(submake_extras) \
-f Makefile.docs \
prefix= OUTPUT=$(OUTPUT)/ DESTDIR=$(OUTPUT)/ $@
$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ $(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
../../../include/uapi/linux/bpf.h \ ../../../include/uapi/linux/bpf.h \
...@@ -477,3 +485,5 @@ EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ ...@@ -477,3 +485,5 @@ EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \
prog_tests/tests.h map_tests/tests.h verifier/tests.h \ prog_tests/tests.h map_tests/tests.h verifier/tests.h \
feature \ feature \
$(addprefix $(OUTPUT)/,*.o *.skel.h no_alu32 bpf_gcc bpf_testmod.ko) $(addprefix $(OUTPUT)/,*.o *.skel.h no_alu32 bpf_gcc bpf_testmod.ko)
.PHONY: docs docs-clean
# SPDX-License-Identifier: GPL-2.0-only
include ../../../scripts/Makefile.include
include ../../../scripts/utilities.mak
INSTALL ?= install
RM ?= rm -f
RMDIR ?= rmdir --ignore-fail-on-non-empty
ifeq ($(V),1)
Q =
else
Q = @
endif
prefix ?= /usr/local
mandir ?= $(prefix)/man
man2dir = $(mandir)/man2
man7dir = $(mandir)/man7
SYSCALL_RST = bpf-syscall.rst
MAN2_RST = $(SYSCALL_RST)
HELPERS_RST = bpf-helpers.rst
MAN7_RST = $(HELPERS_RST)
_DOC_MAN2 = $(patsubst %.rst,%.2,$(MAN2_RST))
DOC_MAN2 = $(addprefix $(OUTPUT),$(_DOC_MAN2))
_DOC_MAN7 = $(patsubst %.rst,%.7,$(MAN7_RST))
DOC_MAN7 = $(addprefix $(OUTPUT),$(_DOC_MAN7))
DOCTARGETS := helpers syscall
docs: $(DOCTARGETS)
syscall: man2
helpers: man7
man2: $(DOC_MAN2)
man7: $(DOC_MAN7)
RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null)
# Configure make rules for the man page bpf-$1.$2.
# $1 - target for scripts/bpf_doc.py
# $2 - man page section to generate the troff file
define DOCS_RULES =
$(OUTPUT)bpf-$1.rst: ../../../../include/uapi/linux/bpf.h
$$(QUIET_GEN)../../../../scripts/bpf_doc.py $1 \
--filename $$< > $$@
$(OUTPUT)%.$2: $(OUTPUT)%.rst
ifndef RST2MAN_DEP
$$(error "rst2man not found, but required to generate man pages")
endif
$$(QUIET_GEN)rst2man $$< > $$@
docs-clean-$1:
$$(call QUIET_CLEAN, eBPF_$1-manpage)
$(Q)$(RM) $$(DOC_MAN$2) $(OUTPUT)bpf-$1.rst
docs-install-$1: docs
$$(call QUIET_INSTALL, eBPF_$1-manpage)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$$(man$2dir)
$(Q)$(INSTALL) -m 644 $$(DOC_MAN$2) $(DESTDIR)$$(man$2dir)
docs-uninstall-$1:
$$(call QUIET_UNINST, eBPF_$1-manpage)
$(Q)$(RM) $$(addprefix $(DESTDIR)$$(man$2dir)/,$$(_DOC_MAN$2))
$(Q)$(RMDIR) $(DESTDIR)$$(man$2dir)
.PHONY: $1 docs-clean-$1 docs-install-$1 docs-uninstall-$1
endef
# Create the make targets to generate manual pages by name and section
$(eval $(call DOCS_RULES,helpers,7))
$(eval $(call DOCS_RULES,syscall,2))
docs-clean: $(foreach doctarget,$(DOCTARGETS), docs-clean-$(doctarget))
docs-install: $(foreach doctarget,$(DOCTARGETS), docs-install-$(doctarget))
docs-uninstall: $(foreach doctarget,$(DOCTARGETS), docs-uninstall-$(doctarget))
.PHONY: docs docs-clean docs-install docs-uninstall man2 man7
...@@ -85,23 +85,6 @@ make_with_tmpdir() { ...@@ -85,23 +85,6 @@ make_with_tmpdir() {
echo echo
} }
make_doc_and_clean() {
echo -e "\$PWD: $PWD"
echo -e "command: make -s $* doc >/dev/null"
RST2MAN_OPTS="--exit-status=1" make $J -s $* doc
if [ $? -ne 0 ] ; then
ERROR=1
printf "FAILURE: Errors or warnings when building documentation\n"
fi
(
if [ $# -ge 1 ] ; then
cd ${@: -1}
fi
make -s doc-clean
)
echo
}
echo "Trying to build bpftool" echo "Trying to build bpftool"
echo -e "... through kbuild\n" echo -e "... through kbuild\n"
...@@ -162,7 +145,3 @@ make_and_clean ...@@ -162,7 +145,3 @@ make_and_clean
make_with_tmpdir OUTPUT make_with_tmpdir OUTPUT
make_with_tmpdir O make_with_tmpdir O
echo -e "Checking documentation build\n"
# From tools/bpf/bpftool
make_doc_and_clean
#!/bin/bash
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Assume script is located under tools/testing/selftests/bpf/. We want to start
# build attempts from the top of kernel repository.
SCRIPT_REL_PATH=$(realpath --relative-to=$PWD $0)
SCRIPT_REL_DIR=$(dirname $SCRIPT_REL_PATH)
KDIR_ROOT_DIR=$(realpath $PWD/$SCRIPT_REL_DIR/../../../../)
cd $KDIR_ROOT_DIR
for tgt in docs docs-clean; do
make -s -C $PWD/$SCRIPT_REL_DIR $tgt;
done
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册