2017-12-18 15:56:25 +00:00
|
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
2019-04-02 03:54:53 +00:00
|
|
|
# Copyright(c) 2017-2019 Intel Corporation
|
2017-11-17 19:37:54 +00:00
|
|
|
|
2017-10-17 12:43:57 +00:00
|
|
|
|
|
|
|
# process all libraries equally, as far as possible
|
|
|
|
# "core" libs first, then others alphebetically as far as possible
|
|
|
|
# NOTE: for speed of meson runs, the dependencies in the subdirectories
|
|
|
|
# sometimes skip deps that would be implied by others, e.g. if mempool is
|
|
|
|
# given as a dep, no need to mention ring. This is especially true for the
|
|
|
|
# core libs which are widely reused, so their deps are kept to a minimum.
|
2019-02-06 11:01:30 +00:00
|
|
|
libraries = [
|
2018-10-22 13:15:30 +00:00
|
|
|
'kvargs', # eal depends on kvargs
|
2019-02-26 17:46:34 +00:00
|
|
|
'eal', # everything depends on eal
|
|
|
|
'ring', 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core
|
2019-07-05 17:16:20 +00:00
|
|
|
'cmdline',
|
2017-10-17 12:43:57 +00:00
|
|
|
'metrics', # bitrate/latency stats depends on this
|
|
|
|
'hash', # efd depends on this
|
2018-04-04 21:51:09 +00:00
|
|
|
'timer', # eventdev depends on this
|
2017-10-17 12:43:57 +00:00
|
|
|
'acl', 'bbdev', 'bitratestats', 'cfgfile',
|
2018-10-22 13:15:30 +00:00
|
|
|
'compressdev', 'cryptodev',
|
2017-10-17 12:43:57 +00:00
|
|
|
'distributor', 'efd', 'eventdev',
|
|
|
|
'gro', 'gso', 'ip_frag', 'jobstats',
|
|
|
|
'kni', 'latencystats', 'lpm', 'member',
|
2018-12-20 12:16:08 +00:00
|
|
|
'power', 'pdump', 'rawdev',
|
2019-11-01 15:21:34 +00:00
|
|
|
'rcu', 'rib', 'reorder', 'sched', 'security', 'stack', 'vhost',
|
2019-06-24 13:39:58 +00:00
|
|
|
# ipsec lib depends on net, crypto and security
|
2019-01-10 21:06:28 +00:00
|
|
|
'ipsec',
|
2019-11-01 15:21:38 +00:00
|
|
|
#fib lib depends on rib
|
|
|
|
'fib',
|
2017-10-17 12:43:57 +00:00
|
|
|
# add pkt framework libs which use other libs from above
|
|
|
|
'port', 'table', 'pipeline',
|
|
|
|
# flow_classify lib depends on pkt framework table lib
|
2018-10-27 09:17:41 +00:00
|
|
|
'flow_classify', 'bpf', 'telemetry']
|
2017-10-17 12:43:57 +00:00
|
|
|
|
2019-04-09 10:55:36 +00:00
|
|
|
if is_windows
|
2019-04-02 03:54:58 +00:00
|
|
|
libraries = ['kvargs','eal'] # only supported libraries for windows
|
|
|
|
endif
|
|
|
|
|
2018-07-19 14:22:06 +00:00
|
|
|
default_cflags = machine_args
|
|
|
|
if cc.has_argument('-Wno-format-truncation')
|
|
|
|
default_cflags += '-Wno-format-truncation'
|
|
|
|
endif
|
2018-08-29 16:19:20 +00:00
|
|
|
|
|
|
|
enabled_libs = [] # used to print summary at the end
|
2018-10-04 10:20:33 +00:00
|
|
|
|
2017-10-17 12:43:57 +00:00
|
|
|
foreach l:libraries
|
|
|
|
build = true
|
2019-06-05 20:22:39 +00:00
|
|
|
reason = '<unknown reason>' # set if build == false to explain why
|
2017-10-17 12:43:57 +00:00
|
|
|
name = l
|
|
|
|
allow_experimental_apis = false
|
2019-10-07 15:45:50 +00:00
|
|
|
use_function_versioning = false
|
2017-10-17 12:43:57 +00:00
|
|
|
sources = []
|
|
|
|
headers = []
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
includes = []
|
2018-07-19 14:22:06 +00:00
|
|
|
cflags = default_cflags
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
objs = [] # other object files to link against, used e.g. for
|
|
|
|
# instruction-set optimized versions of code
|
|
|
|
|
2017-10-17 12:43:57 +00:00
|
|
|
# use "deps" for internal DPDK dependencies, and "ext_deps" for
|
|
|
|
# external package/library requirements
|
|
|
|
ext_deps = []
|
2018-07-19 14:37:02 +00:00
|
|
|
deps = []
|
|
|
|
# eal is standard dependency once built
|
|
|
|
if dpdk_conf.has('RTE_LIBRTE_EAL')
|
|
|
|
deps += ['eal']
|
2018-07-11 21:44:54 +00:00
|
|
|
endif
|
2017-10-17 12:43:57 +00:00
|
|
|
|
|
|
|
dir_name = 'librte_' + l
|
|
|
|
subdir(dir_name)
|
|
|
|
|
2019-09-25 14:55:30 +00:00
|
|
|
if build
|
|
|
|
shared_deps = ext_deps
|
|
|
|
static_deps = ext_deps
|
|
|
|
foreach d:deps
|
|
|
|
if not is_variable('shared_rte_' + d)
|
|
|
|
error('Missing internal dependency "@0@" for @1@ [@2@]'
|
|
|
|
.format(d, name, 'lib/' + dir_name))
|
|
|
|
endif
|
|
|
|
shared_deps += [get_variable('shared_rte_' + d)]
|
|
|
|
static_deps += [get_variable('static_rte_' + d)]
|
|
|
|
endforeach
|
|
|
|
endif
|
|
|
|
|
2019-06-05 20:22:39 +00:00
|
|
|
if not build
|
|
|
|
dpdk_libs_disabled += name
|
|
|
|
set_variable(name.underscorify() + '_disable_reason', reason)
|
|
|
|
else
|
2018-08-29 16:19:20 +00:00
|
|
|
enabled_libs += name
|
2017-10-17 12:43:57 +00:00
|
|
|
dpdk_conf.set('RTE_LIBRTE_' + name.to_upper(), 1)
|
|
|
|
install_headers(headers)
|
|
|
|
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
libname = 'rte_' + name
|
|
|
|
includes += include_directories(dir_name)
|
2017-10-17 12:43:57 +00:00
|
|
|
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
if sources.length() == 0
|
|
|
|
# if no C files, just set a dependency on header path
|
2017-11-03 17:27:32 +00:00
|
|
|
shared_dep = declare_dependency(include_directories: includes)
|
|
|
|
static_dep = shared_dep
|
2017-08-31 10:36:43 +00:00
|
|
|
else
|
|
|
|
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
if allow_experimental_apis
|
|
|
|
cflags += '-DALLOW_EXPERIMENTAL_API'
|
|
|
|
endif
|
2019-10-07 15:45:50 +00:00
|
|
|
if use_function_versioning
|
|
|
|
cflags += '-DRTE_USE_FUNCTION_VERSIONING'
|
|
|
|
endif
|
2017-10-17 12:43:57 +00:00
|
|
|
|
2019-11-20 17:23:28 +00:00
|
|
|
version_map = '@0@/@1@/rte_@2@_version.map'.format(
|
|
|
|
meson.current_source_dir(), dir_name, name)
|
|
|
|
|
|
|
|
is_experimental = run_command(is_experimental_cmd,
|
|
|
|
files(version_map)).returncode()
|
|
|
|
|
|
|
|
if is_experimental != 0
|
|
|
|
lib_version = experimental_abi_version
|
2019-12-12 11:58:26 +00:00
|
|
|
so_version = experimental_so_version
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
else
|
2019-11-20 17:23:28 +00:00
|
|
|
lib_version = abi_version
|
2019-12-12 11:58:26 +00:00
|
|
|
so_version = stable_so_version
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
endif
|
|
|
|
|
2017-11-03 17:27:32 +00:00
|
|
|
# first build static lib
|
|
|
|
static_lib = static_library(libname,
|
|
|
|
sources,
|
|
|
|
objects: objs,
|
|
|
|
c_args: cflags,
|
|
|
|
dependencies: static_deps,
|
|
|
|
include_directories: includes,
|
|
|
|
install: true)
|
|
|
|
static_dep = declare_dependency(link_with: static_lib,
|
|
|
|
include_directories: includes,
|
|
|
|
dependencies: static_deps)
|
|
|
|
|
2019-10-07 15:45:50 +00:00
|
|
|
if not use_function_versioning
|
|
|
|
# use pre-build objects to build shared lib
|
|
|
|
sources = []
|
|
|
|
objs += static_lib.extract_all_objects(recursive: false)
|
|
|
|
else
|
|
|
|
# for compat we need to rebuild with
|
|
|
|
# RTE_BUILD_SHARED_LIB defined
|
|
|
|
cflags += '-DRTE_BUILD_SHARED_LIB'
|
|
|
|
endif
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
version_map = '@0@/@1@/rte_@2@_version.map'.format(
|
|
|
|
meson.current_source_dir(), dir_name, name)
|
2019-04-02 03:54:53 +00:00
|
|
|
implib = dir_name + '.dll.a'
|
2019-04-12 08:29:00 +00:00
|
|
|
|
|
|
|
def_file = custom_target(name + '_def',
|
|
|
|
command: [map_to_def_cmd, '@INPUT@', '@OUTPUT@'],
|
|
|
|
input: version_map,
|
|
|
|
output: 'rte_@0@_exports.def'.format(name))
|
2019-10-08 14:36:27 +00:00
|
|
|
lk_deps = [version_map, def_file]
|
2019-04-09 10:55:36 +00:00
|
|
|
if is_windows
|
2019-04-12 08:29:00 +00:00
|
|
|
lk_args = ['-Wl,/def:' + def_file.full_path(),
|
|
|
|
'-Wl,/implib:lib\\' + implib]
|
2019-04-02 03:54:53 +00:00
|
|
|
else
|
|
|
|
lk_args = ['-Wl,--version-script=' + version_map]
|
2019-10-08 14:36:27 +00:00
|
|
|
# on unix systems check the output of the
|
|
|
|
# experimental syms script, using it as a
|
|
|
|
# dependency of the .so build
|
|
|
|
lk_deps += custom_target(name + '.exp_chk',
|
|
|
|
command: [check_experimental_syms,
|
|
|
|
version_map, '@INPUT@'],
|
|
|
|
capture: true,
|
|
|
|
input: static_lib,
|
|
|
|
output: name + '.exp_chk')
|
2019-04-02 03:54:53 +00:00
|
|
|
endif
|
2019-04-12 08:29:00 +00:00
|
|
|
|
2017-11-03 17:27:32 +00:00
|
|
|
shared_lib = shared_library(libname,
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
sources,
|
|
|
|
objects: objs,
|
|
|
|
c_args: cflags,
|
2017-11-03 17:27:32 +00:00
|
|
|
dependencies: shared_deps,
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
include_directories: includes,
|
2019-04-02 03:54:53 +00:00
|
|
|
link_args: lk_args,
|
2019-10-08 14:36:27 +00:00
|
|
|
link_depends: lk_deps,
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
version: lib_version,
|
|
|
|
soversion: so_version,
|
|
|
|
install: true)
|
2017-11-03 17:27:32 +00:00
|
|
|
shared_dep = declare_dependency(link_with: shared_lib,
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
include_directories: includes,
|
2017-11-03 17:27:32 +00:00
|
|
|
dependencies: shared_deps)
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
|
2017-11-03 17:27:32 +00:00
|
|
|
dpdk_libraries = [shared_lib] + dpdk_libraries
|
2018-10-27 09:17:50 +00:00
|
|
|
dpdk_static_libraries = [static_lib] + dpdk_static_libraries
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
endif # sources.length() > 0
|
|
|
|
|
2019-09-19 15:07:55 +00:00
|
|
|
set_variable('shared_rte_' + name, shared_dep)
|
|
|
|
set_variable('static_rte_' + name, static_dep)
|
|
|
|
message('lib/@0@: Defining dependency "@1@"'.format(
|
|
|
|
dir_name, name))
|
build: remove library special cases
The EAL and compat libraries were special-cases in the library build
process, the former because of it's complexity, and the latter because
it only consists of a single header file.
By reworking the EAL meson.build files, we can eliminate the need for it to
be a special case, by having it build up and return the list of sources,
headers, and objects and return those to the higher level build file. This
should also simplify the building of EAL, as we can eliminate a number of
meson.build files that would no longer be needed, and have fewer, but
larger meson.build files (9 now vs 14 previous) - thereby making the logic
easier to follow and items easier to find.
Once done, we can pull eal into the main library loop, with some
modifications to support it. Compat can also be pulled it once we add in a
check to handle the case of an empty sources list.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Luca Boccassi <bluca@debian.org>
2017-11-03 14:47:43 +00:00
|
|
|
endif # if build
|
2017-10-17 12:43:57 +00:00
|
|
|
endforeach
|