meson: add experimental bpf-gcc compiler support

Not fully working but should make it easier to clean up remaining
issues.
This commit is contained in:
James Hilliard 2022-06-08 10:13:42 +00:00 committed by Zbigniew Jędrzejewski-Szmek
parent 02bf03405b
commit 76abad4d47
3 changed files with 93 additions and 54 deletions

View File

@ -1020,58 +1020,74 @@ conf.set10('HAVE_LIBBPF', libbpf.found())
if want_bpf_framework == 'false' or not libbpf.found() or skip_deps
conf.set10('BPF_FRAMEWORK', false)
else
# Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
# (like clang-10/llvm-strip-10)
if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
r = find_program('clang', required : bpf_framework_required, version : '>= 10.0.0')
clang_found = r.found()
if clang_found
clang = r.path()
bpf_compiler = get_option('bpf-compiler')
clang_found = false
clang_supports_bpf = false
bpf_gcc_found = false
deps_found = false
if bpf_compiler == 'clang'
# Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
# (like clang-10/llvm-strip-10)
if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
r = find_program('clang', required : bpf_framework_required, version : '>= 10.0.0')
clang_found = r.found()
if clang_found
clang = r.path()
endif
# Assume that the required flags are supported by the found clang.
clang_supports_flags = clang_found
else
clang_found = true
clang = cc.cmd_array()
clang_supports_flags = cc.has_argument('-Wno-compare-distinct-pointer-types')
endif
# Assume that the required flags are supported by the found clang.
clang_supports_flags = clang_found
else
clang_found = true
clang = cc.cmd_array()
clang_supports_flags = cc.has_argument('-Wno-compare-distinct-pointer-types')
if clang_found
# Check if 'clang -target bpf' is supported.
clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
endif
elif bpf_compiler == 'gcc'
warning('GCC BPF Compiler support is experimental and not recommended.')
bpf_gcc = find_program('bpf-gcc',
required : true,
version : '>= 12.1.0')
bpf_gcc_found = bpf_gcc.found()
endif
if clang_found
# Check if 'clang -target bpf' is supported.
clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
else
clang_supports_bpf = false
endif
# Debian installs this in /usr/sbin/ which is not in $PATH.
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
# We use 'bpftool gen' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : false,
version : '>= 5.13.0')
if bpftool.found()
bpftool_strip = true
else
bpftool_strip = false
if clang_supports_bpf or bpf_gcc_found
# Debian installs this in /usr/sbin/ which is not in $PATH.
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
# We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework_required,
version : '>= 5.6.0')
endif
required : false,
version : '>= 5.13.0')
if not bpftool_strip
if not meson.is_cross_build() and clang_found
llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
check : true).stdout().strip()
if bpftool.found()
bpftool_strip = true
deps_found = true
else
llvm_strip_bin = 'llvm-strip'
bpftool_strip = false
# We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework_required,
version : '>= 5.6.0')
endif
llvm_strip = find_program(llvm_strip_bin, required : bpf_framework_required, version : '>= 10.0.0')
endif
deps_found = clang_found and clang_supports_bpf and clang_supports_flags and (bpftool_strip or llvm_strip.found()) and bpftool.found()
# We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
if not bpftool_strip and bpftool.found() and clang_supports_bpf
if not meson.is_cross_build()
llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
check : true).stdout().strip()
else
llvm_strip_bin = 'llvm-strip'
endif
llvm_strip = find_program(llvm_strip_bin, required : bpf_framework_required, version : '>= 10.0.0')
deps_found = llvm_strip.found()
endif
endif
# Can build BPF program from source code in restricted C
conf.set10('BPF_FRAMEWORK', deps_found)

View File

@ -496,6 +496,8 @@ option('kernel-install', type: 'boolean', value: 'true',
option('analyze', type: 'boolean', value: 'true',
description : 'install systemd-analyze')
option('bpf-compiler', type : 'combo', choices : ['clang', 'gcc'],
description: 'compiler used to build BPF programs, note: gcc is experimental')
option('bpf-framework', type : 'combo', choices : ['auto', 'true', 'false'],
description: 'build BPF programs from source code in restricted C')

View File

@ -4,7 +4,7 @@ if conf.get('BPF_FRAMEWORK') != 1
subdir_done()
endif
clang_flags = [
bpf_clang_flags = [
'-Wno-compare-distinct-pointer-types',
'-O2',
'-target',
@ -13,6 +13,14 @@ clang_flags = [
'-c',
]
bpf_gcc_flags = [
'-O2',
'-mkernel=5.2',
'-mcpu=v3',
'-mco-re',
'-gbtf',
]
# Generate defines that are appropriate to tell the compiler what architecture
# we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
# This dictionary contains the exceptions where this doesn't work.
@ -30,19 +38,32 @@ cpu_arch_defines = {
'arm' : ['-D__arm__', '-D__ARM_PCS_VFP'],
}
clang_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
['-D__@0@__'.format(host_machine.cpu_family())])
bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
['-D__@0@__'.format(host_machine.cpu_family())])
if bpf_compiler == 'gcc'
bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
endif
libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
bpf_o_unstripped_cmd = [
clang,
clang_flags,
clang_arch_flags,
'-I.'
]
bpf_o_unstripped_cmd = []
if bpf_compiler == 'clang'
bpf_o_unstripped_cmd += [
clang,
bpf_clang_flags,
bpf_arch_flags,
]
elif bpf_compiler == 'gcc'
bpf_o_unstripped_cmd += [
bpf_gcc,
bpf_gcc_flags,
bpf_arch_flags,
]
endif
if not meson.is_cross_build()
bpf_o_unstripped_cmd += ['-I.']
if not meson.is_cross_build() and bpf_compiler == 'clang'
target_triplet_cmd = run_command('gcc', '-dumpmachine', check: false)
if target_triplet_cmd.returncode() == 0
target_triplet = target_triplet_cmd.stdout().strip()
@ -69,7 +90,7 @@ if bpftool_strip
'@OUTPUT@',
'@INPUT@'
]
else
elif bpf_compiler == 'clang'
bpf_o_cmd = [
llvm_strip,
'-g',