]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
meson: add experimental bpf-gcc compiler support
authorJames Hilliard <james.hilliard1@gmail.com>
Wed, 8 Jun 2022 10:13:42 +0000 (10:13 +0000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 10 Jun 2022 12:01:19 +0000 (14:01 +0200)
Not fully working but should make it easier to clean up remaining
issues.

meson.build
meson_options.txt
src/core/bpf/meson.build

index 4a114ed51b9fb1ed5bdb00f1d2574415e768ebb7..62c605129f547d79844076da7c508ebba49e9662 100644 (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')
-        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
+                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
 
-        # 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)
index 3bb25c6f763f0e93bb17a8d7e7072e08e8b876df..3a1d7ce0ec006e12052af27f1fb4a3728cf2287f 100644 (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')
 
index c88e45771695d7e04699596f3e7df1214ce415f0..c2f9b5ac4286a8f79486e91b53e16f10354e62af 100644 (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
+
+bpf_o_unstripped_cmd += ['-I.']
 
-if not meson.is_cross_build()
+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',