xref: /dpdk/drivers/meson.build (revision c1d145834f287aa8cf53de914618a7312f2c360e)
1# SPDX-License-Identifier: BSD-3-Clause
2# Copyright(c) 2017-2019 Intel Corporation
3
4if is_ms_compiler
5    subdir_done()
6endif
7
8fs = import('fs')
9
10# Defines the order of dependencies evaluation
11subdirs = [
12        'common',
13        'bus',
14        'common/cnxk',    # depends on bus.
15        'common/mlx5',    # depends on bus.
16        'common/nfp',     # depends on bus.
17        'common/nitrox',  # depends on bus.
18        'common/qat',     # depends on bus.
19        'common/sfc_efx', # depends on bus.
20        'mempool',        # depends on common and bus.
21        'dma',            # depends on common and bus.
22        'net',            # depends on common, bus, mempool
23        'raw',            # depends on common, bus, dma and net.
24        'crypto',         # depends on common, bus and mempool (net in future).
25        'compress',       # depends on common, bus, mempool.
26        'regex',          # depends on common, bus, regexdev.
27        'ml',             # depends on common, bus and mempool
28        'vdpa',           # depends on common, bus and mempool.
29        'event',          # depends on common, bus, mempool and net.
30        'baseband',       # depends on common and bus.
31        'gpu',            # depends on common and bus.
32        'power',
33]
34
35if meson.is_cross_build()
36    disable_drivers += ',' + meson.get_external_property('disable_drivers', '')
37    enable_drivers += ',' + meson.get_external_property('enable_drivers', '')
38endif
39
40# add cmdline disabled drivers and meson disabled drivers together
41disable_drivers += ',' + get_option('disable_drivers')
42disable_drivers = run_command(list_dir_globs, disable_drivers, check: true).stdout().split()
43
44# add cmdline enabled drivers and meson enabled drivers together
45enable_drivers = ',' + get_option('enable_drivers')
46enable_drivers = run_command(list_dir_globs, enable_drivers, check: true).stdout().split()
47require_drivers = true
48if enable_drivers.length() == 0
49    require_drivers = false
50    enable_drivers = run_command(list_dir_globs, '*/*,*/*/*', check: true).stdout().split()
51endif
52
53# these drivers must always be enabled, otherwise the build breaks
54always_enable = ['bus/pci', 'bus/vdev']
55# we always need a mempool driver, and ring is default, so make it mandatory
56always_enable += ['mempool/ring']
57enable_drivers += always_enable
58
59default_cflags = machine_args
60default_cflags += ['-DALLOW_EXPERIMENTAL_API']
61default_cflags += ['-DALLOW_INTERNAL_API']
62
63warning_disable_cflags = ['-Wno-format-truncation', '-Wno-address-of-packed-member']
64foreach cflag:warning_disable_cflags
65    if cc.has_argument(cflag)
66        default_cflags += cflag
67    endif
68endforeach
69
70dpdk_drivers_build_dir = meson.current_build_dir()
71
72foreach subpath:subdirs
73    drivers = []
74    std_deps = []
75    log_prefix = ''
76
77    # subpath can be either "class" or "class/driver"
78    if subpath.contains('/')
79        driver_path = subpath.split('/')
80        class = driver_path[0]
81        drivers += driver_path[1]
82    else
83        class = subpath
84        subdir(class)
85        skip_class = false
86        foreach d:std_deps
87            if not is_variable('shared_rte_' + d)
88                skip_class = true
89                reason = 'missing internal dependency, "@0@"'.format(d)
90                if dpdk_libs_deprecated.contains(d)
91                    reason += ' (deprecated lib)'
92                endif
93                message('Disabling @1@/* drivers: missing internal dependency "@0@"'
94                        .format(d, class))
95                break
96            endif
97        endforeach
98        if skip_class
99            drv_path = join_paths(class, '*')
100            dpdk_drvs_disabled += drv_path
101            set_variable('drv_' + drv_path.underscorify() + '_disable_reason', reason)
102            continue
103        endif
104    endif
105
106    # save class name on first occurrence
107    if not dpdk_driver_classes.contains(class)
108        dpdk_driver_classes += class
109    endif
110    # get already enabled drivers of the same class
111    enabled_drivers = get_variable(class + '_drivers', [])
112
113    # default log prefix can be defined per class
114    if log_prefix == ''
115        # default log name is pmd.class.driver
116        log_prefix = 'pmd.' + class
117    endif
118
119    foreach drv:drivers
120        drv_path = join_paths(class, drv)
121
122        # set up empty variables used for build
123        build = true # set to false to disable, e.g. missing deps
124        reason = '<unknown reason>' # set if build == false to explain
125        name = drv
126        annotate_locks = true
127        sources = []
128        headers = []
129        driver_sdk_headers = [] # public headers included by drivers
130        objs = []
131        cflags = default_cflags
132        includes = [include_directories(drv_path)]
133        # set up internal deps. Drivers can append/override as necessary
134        deps = std_deps
135        # ext_deps: Stores external library dependency got
136        # using dependency() (preferred) or find_library().
137        # For the find_library() case (but not with dependency()) we also
138        # need to specify the "-l" flags in pkgconfig_extra_libs variable
139        # too, so that it can be reflected in the pkgconfig output for
140        # static builds.
141        ext_deps = []
142        pkgconfig_extra_libs = []
143        testpmd_sources = []
144        require_iova_in_mbuf = true
145
146        if name.contains('/')
147            name = name.split('/')[1]
148        endif
149
150        if not enable_drivers.contains(drv_path)
151            build = false
152            reason = 'not in enabled drivers build config'
153        elif disable_drivers.contains(drv_path)
154            if always_enable.contains(drv_path)
155                message('Driver @0@ cannot be disabled, not disabling.'.format(drv_path))
156            else
157                build = false
158                reason = 'explicitly disabled via build config'
159            endif
160        endif
161
162        if build
163            # pull in driver directory which should update all the local variables
164            subdir(drv_path)
165
166            if dpdk_conf.get('RTE_IOVA_IN_MBUF') == 0 and require_iova_in_mbuf
167                build = false
168                reason = 'requires IOVA in mbuf (set enable_iova_as_pa option)'
169            endif
170            # error out if we can't build a driver and that driver was explicitly requested,
171            # i.e. not via wildcard.
172            if not build and require_drivers and get_option('enable_drivers').contains(drv_path)
173                error('Cannot build explicitly requested driver "@0@".\n'.format(drv_path)
174                        +'\tReason: ' + reason)
175            endif
176
177            # get dependency objs from strings
178            shared_deps = ext_deps
179            static_deps = ext_deps
180            foreach d:deps
181                if not build
182                    break
183                endif
184                if not is_variable('shared_rte_' + d)
185                    build = false
186                    reason = 'missing internal dependency, "@0@"'.format(d)
187                    if dpdk_libs_deprecated.contains(d)
188                        reason += ' (deprecated lib)'
189                    endif
190                    message('Disabling @1@ [@2@]: missing internal dependency "@0@"'
191                            .format(d, name, 'drivers/' + drv_path))
192                    # error out if we can't build a driver and that driver was explicitly
193                    # requested, i.e. not via wildcard.
194                    if require_drivers and get_option('enable_drivers').contains(drv_path)
195                        error('Cannot build explicitly requested driver "@0@".\n'.format(drv_path)
196                                +'\tPlease enable missing dependency "@0@"'.format(d))
197                    endif
198                else
199                    shared_deps += [get_variable('shared_rte_' + d)]
200                    static_deps += [get_variable('static_rte_' + d)]
201                endif
202            endforeach
203        endif
204
205        if not build
206            # some driver directories are placeholders which
207            # are never built, so we allow suppression of the
208            # component disable printout in those cases
209            if reason != ''
210                dpdk_drvs_disabled += drv_path
211                set_variable('drv_' + drv_path.underscorify() + '_disable_reason', reason)
212            endif
213            continue
214        endif
215
216        enabled_drivers += name
217        lib_name = '_'.join(['rte', class, name])
218        cflags += '-DRTE_LOG_DEFAULT_LOGTYPE=' + '.'.join([log_prefix, name])
219        if annotate_locks and cc.get_id() == 'clang' and cc.version().version_compare('>=3.5.0')
220            cflags += '-DRTE_ANNOTATE_LOCKS'
221            cflags += '-Wthread-safety'
222        endif
223        dpdk_conf.set(lib_name.to_upper(), 1)
224
225        dpdk_extra_ldflags += pkgconfig_extra_libs
226
227        install_headers(headers)
228        if get_option('enable_driver_sdk')
229            install_headers(driver_sdk_headers)
230        endif
231        dpdk_chkinc_headers += driver_sdk_headers
232
233        if headers.length() > 0
234            dpdk_includes += include_directories(drv_path)
235        endif
236
237        # generate pmdinfo sources by building a temporary
238        # lib and then running pmdinfogen on the contents of
239        # that lib. The final lib reuses the object files and
240        # adds in the new source file.
241        out_filename = lib_name + '.pmd.c'
242        tmp_lib = static_library('tmp_' + lib_name, sources,
243                include_directories: includes,
244                dependencies: static_deps,
245                c_args: cflags)
246        objs += tmp_lib.extract_all_objects(recursive: true)
247        sources = custom_target(out_filename,
248                command: [pmdinfo, tmp_lib.full_path(), '@OUTPUT@', pmdinfogen],
249                output: out_filename,
250                depends: [tmp_lib])
251
252        # now build the static driver
253        static_lib = static_library(lib_name,
254                sources,
255                objects: objs,
256                include_directories: includes,
257                dependencies: static_deps,
258                c_args: cflags,
259                install: true)
260
261        # now build the shared driver
262        version_map = '@0@/@1@/version.map'.format(meson.current_source_dir(), drv_path)
263
264        lk_deps = []
265        lk_args = []
266        if not fs.is_file(version_map)
267            version_map = '@0@/version.map'.format(meson.current_source_dir())
268            lk_deps += [version_map]
269        else
270            lk_deps += [version_map]
271            if not is_windows and developer_mode
272                # on unix systems check the output of the
273                # check-symbols.sh script, using it as a
274                # dependency of the .so build
275                lk_deps += custom_target(lib_name + '.sym_chk',
276                        command: [check_symbols, version_map, '@INPUT@'],
277                        capture: true,
278                        input: static_lib,
279                        output: lib_name + '.sym_chk')
280            endif
281        endif
282
283        if is_windows
284            if is_ms_linker
285                def_file = custom_target(lib_name + '_def',
286                        command: [map_to_win_cmd, '@INPUT@', '@OUTPUT@'],
287                        input: version_map,
288                        output: '@0@_exports.def'.format(lib_name))
289                lk_deps += [def_file]
290
291                lk_args = ['-Wl,/def:' + def_file.full_path()]
292            else
293                mingw_map = custom_target(lib_name + '_mingw',
294                        command: [map_to_win_cmd, '@INPUT@', '@OUTPUT@'],
295                        input: version_map,
296                        output: '@0@_mingw.map'.format(lib_name))
297                lk_deps += [mingw_map]
298
299                lk_args = ['-Wl,--version-script=' + mingw_map.full_path()]
300            endif
301        else
302            lk_args = ['-Wl,--version-script=' + version_map]
303        endif
304
305        shared_lib = shared_library(lib_name, sources,
306                objects: objs,
307                include_directories: includes,
308                dependencies: shared_deps,
309                c_args: cflags,
310                link_args: lk_args,
311                link_depends: lk_deps,
312                version: abi_version,
313                soversion: so_version,
314                install: true,
315                install_dir: driver_install_path)
316
317        # create a dependency object and add it to the global dictionary so
318        # testpmd or other built-in apps can find it if necessary
319        shared_dep = declare_dependency(link_with: shared_lib,
320                include_directories: includes,
321                dependencies: shared_deps)
322        static_dep = declare_dependency(
323                include_directories: includes,
324                dependencies: static_deps)
325
326        dpdk_drivers += static_lib
327
328        set_variable('shared_@0@'.format(lib_name), shared_dep)
329        set_variable('static_@0@'.format(lib_name), static_dep)
330        # for drivers, we only need to add dependency objects for static libs,
331        # shared lib drivers are not linked in
332        dpdk_static_lib_deps += static_dep
333
334        dependency_name = ''.join(lib_name.split('rte_'))
335        if testpmd_sources.length() != 0
336            testpmd_drivers_sources += testpmd_sources
337            testpmd_drivers_deps += dependency_name
338        endif
339        if developer_mode
340            message('drivers/@0@: Defining dependency "@1@"'.format(
341                    drv_path, dependency_name))
342        endif
343    endforeach
344
345    set_variable(class + '_drivers', enabled_drivers)
346endforeach
347