summaryrefslogtreecommitdiffstats
path: root/src/seastar/configure.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/seastar/configure.py
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/seastar/configure.py')
-rwxr-xr-xsrc/seastar/configure.py251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/seastar/configure.py b/src/seastar/configure.py
new file mode 100755
index 000000000..8291210db
--- /dev/null
+++ b/src/seastar/configure.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+#
+# This file is open source software, licensed to you under the terms
+# of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+# distributed with this work for additional information regarding copyright
+# ownership. You may not use this file except in compliance with the License.
+#
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+import argparse
+import os
+import seastar_cmake
+import subprocess
+import tempfile
+
+tempfile.tempdir = "./build/tmp"
+
+def add_tristate(arg_parser, name, dest, help, default=None):
+ arg_parser.add_argument('--enable-' + name, dest = dest, action = 'store_true', default = default,
+ help = 'Enable ' + help + ' [default]' if default else '')
+ arg_parser.add_argument('--disable-' + name, dest = dest, action = 'store_false', default = None,
+ help = 'Disable ' + help)
+
+def try_compile(compiler, source = '', flags = []):
+ return try_compile_and_link(compiler, source, flags = flags + ['-c'])
+
+def ensure_tmp_dir_exists():
+ if not os.path.exists(tempfile.tempdir):
+ os.makedirs(tempfile.tempdir)
+
+def try_compile_and_link(compiler, source = '', flags = []):
+ ensure_tmp_dir_exists()
+ with tempfile.NamedTemporaryFile() as sfile:
+ ofd, ofile = tempfile.mkstemp()
+ os.close(ofd)
+ try:
+ sfile.file.write(bytes(source, 'utf-8'))
+ sfile.file.flush()
+ # We can't write to /dev/null, since in some cases (-ftest-coverage) gcc will create an auxiliary
+ # output file based on the name of the output file, and "/dev/null.gcsa" is not a good name
+ return subprocess.call([compiler, '-x', 'c++', '-o', ofile, sfile.name] + flags,
+ stdout = subprocess.DEVNULL,
+ stderr = subprocess.DEVNULL) == 0
+ finally:
+ if os.path.exists(ofile):
+ os.unlink(ofile)
+def standard_supported(standard, compiler='g++'):
+ return try_compile(compiler=compiler, source='', flags=['-std=' + standard])
+
+arg_parser = argparse.ArgumentParser('Configure seastar')
+arg_parser.add_argument('--mode', action='store', choices=seastar_cmake.SUPPORTED_MODES + ['all'], default='all')
+arg_parser.add_argument('--cflags', action = 'store', dest = 'user_cflags', default = '',
+ help = 'Extra flags for the C++ compiler')
+arg_parser.add_argument('--ldflags', action = 'store', dest = 'user_ldflags', default = '',
+ help = 'Extra flags for the linker')
+arg_parser.add_argument('--optflags', action = 'store', dest = 'user_optflags', default = '',
+ help = 'Extra optimization flags for the release mode')
+arg_parser.add_argument('--api-level', action='store', dest='api_level', default='6',
+ help='Compatibility API level (6=latest)')
+arg_parser.add_argument('--compiler', action = 'store', dest = 'cxx', default = 'g++',
+ help = 'C++ compiler path')
+arg_parser.add_argument('--c-compiler', action='store', dest='cc', default='gcc',
+ help = 'C compiler path (for bundled libraries such as dpdk)')
+arg_parser.add_argument('--c++-standard', action='store', dest='cpp_standard', default='',
+ help='C++ standard to build with [default: %(default)s]')
+arg_parser.add_argument('--cook', action='append', dest='cook', default=[],
+ help='Supply this dependency locally for development via `cmake-cooking` (can be repeated)')
+arg_parser.add_argument('--verbose', dest='verbose', action='store_true', help='Make configure output more verbose.')
+arg_parser.add_argument('--scheduling-groups-count', action='store', dest='scheduling_groups_count', default='16',
+ help='Number of available scheduling groups in the reactor')
+
+add_tristate(
+ arg_parser,
+ name = 'dpdk',
+ dest = 'dpdk',
+ help = 'DPDK support')
+add_tristate(
+ arg_parser,
+ name = 'hwloc',
+ dest = 'hwloc',
+ help = 'hwloc support')
+add_tristate(
+ arg_parser,
+ name = 'alloc-failure-injector',
+ dest = 'alloc_failure_injection',
+ help = 'allocation failure injection')
+add_tristate(
+ arg_parser,
+ name = 'task-backtrace',
+ dest = 'task_backtrace',
+ help = 'Collect backtrace at deferring points')
+add_tristate(
+ arg_parser,
+ name = 'unused-result-error',
+ dest = "unused_result_error",
+ help = 'Make [[nodiscard]] violations an error')
+add_tristate(
+ arg_parser,
+ name = 'debug-shared-ptr',
+ dest = "debug_shared_ptr",
+ help = 'Debug shared_ptr')
+add_tristate(
+ arg_parser,
+ name='io_uring',
+ dest='io_uring',
+ help='Support io_uring via liburing')
+arg_parser.add_argument('--allocator-page-size', dest='alloc_page_size', type=int, help='override allocator page size')
+arg_parser.add_argument('--without-tests', dest='exclude_tests', action='store_true', help='Do not build tests by default')
+arg_parser.add_argument('--without-apps', dest='exclude_apps', action='store_true', help='Do not build applications by default')
+arg_parser.add_argument('--without-demos', dest='exclude_demos', action='store_true', help='Do not build demonstrations by default')
+arg_parser.add_argument('--split-dwarf', dest='split_dwarf', action='store_true', default=False,
+ help='use of split dwarf (https://gcc.gnu.org/wiki/DebugFission) to speed up linking')
+arg_parser.add_argument('--compile-commands-json', dest='cc_json', action='store_true',
+ help='Generate a compile_commands.json file for integration with clangd and other tools.')
+arg_parser.add_argument('--heap-profiling', dest='heap_profiling', action='store_true', default=False, help='Enable heap profiling')
+add_tristate(arg_parser, name='deferred-action-require-noexcept', dest='deferred_action_require_noexcept', help='noexcept requirement for deferred actions', default=True)
+arg_parser.add_argument('--prefix', dest='install_prefix', default='/usr/local', help='Root installation path of Seastar files')
+args = arg_parser.parse_args()
+
+def identify_best_standard(cpp_standards, compiler):
+ """Returns the first C++ standard accepted by the compiler in the sequence,
+ assuming the "best" standards appear first.
+
+ If no standards are accepted, we fail configure.py. There is not point
+ of letting the user attempt to build with a standard that is known not
+ to be supported.
+ """
+ for std in cpp_standards:
+ if standard_supported('c++{}'.format(std), compiler):
+ return std
+ raise Exception(f"{compiler} does not seem to support any of Seastar's preferred C++ standards - {cpp_standards}. Please upgrade your compiler.")
+
+if args.cpp_standard == '':
+ cpp_standards = ['23', '20', '17']
+ args.cpp_standard = identify_best_standard(cpp_standards, compiler=args.cxx)
+
+def infer_dpdk_machine(user_cflags):
+ """Infer the DPDK machine identifier (e.g., 'ivb') from the space-separated
+ string of user cflags by scraping the value of `-march` if it is present.
+
+ The default if no architecture is indicated is 'native'.
+ """
+ arch = 'native'
+
+ # `-march` may be repeated, and we want the last one.
+ # strip features, leave only the arch: armv8-a+crc+crypto -> armv8-a
+ for flag in user_cflags.split():
+ if flag.startswith('-march'):
+ arch = flag[7:].split('+')[0]
+
+ MAPPING = {
+ 'native': 'native',
+ 'nehalem': 'nhm',
+ 'westmere': 'wsm',
+ 'sandybridge': 'snb',
+ 'ivybridge': 'ivb',
+ 'armv8-a': 'armv8a',
+ }
+
+ return MAPPING.get(arch, 'native')
+
+MODES = seastar_cmake.SUPPORTED_MODES if args.mode == 'all' else [args.mode]
+
+# For convenience.
+tr = seastar_cmake.translate_arg
+
+MODE_TO_CMAKE_BUILD_TYPE = {'release' : 'RelWithDebInfo', 'debug' : 'Debug', 'dev' : 'Dev', 'sanitize' : 'Sanitize' }
+
+def configure_mode(mode):
+ BUILD_PATH = seastar_cmake.BUILD_PATHS[mode]
+
+ CFLAGS = seastar_cmake.convert_strings_to_cmake_list(
+ args.user_cflags,
+ args.user_optflags if seastar_cmake.is_release_mode(mode) else '')
+
+ LDFLAGS = seastar_cmake.convert_strings_to_cmake_list(args.user_ldflags)
+
+ TRANSLATED_ARGS = [
+ '-DCMAKE_BUILD_TYPE={}'.format(MODE_TO_CMAKE_BUILD_TYPE[mode]),
+ '-DCMAKE_C_COMPILER={}'.format(args.cc),
+ '-DCMAKE_CXX_COMPILER={}'.format(args.cxx),
+ '-DCMAKE_CXX_STANDARD={}'.format(args.cpp_standard),
+ '-DCMAKE_INSTALL_PREFIX={}'.format(args.install_prefix),
+ '-DCMAKE_EXPORT_COMPILE_COMMANDS={}'.format('yes' if args.cc_json else 'no'),
+ '-DSeastar_API_LEVEL={}'.format(args.api_level),
+ '-DSeastar_SCHEDULING_GROUPS_COUNT={}'.format(args.scheduling_groups_count),
+ tr(args.exclude_tests, 'EXCLUDE_TESTS_FROM_ALL'),
+ tr(args.exclude_apps, 'EXCLUDE_APPS_FROM_ALL'),
+ tr(args.exclude_demos, 'EXCLUDE_DEMOS_FROM_ALL'),
+ tr(CFLAGS, 'CXX_FLAGS'),
+ tr(LDFLAGS, 'LD_FLAGS'),
+ tr(args.dpdk, 'DPDK'),
+ tr(infer_dpdk_machine(args.user_cflags), 'DPDK_MACHINE'),
+ tr(args.hwloc, 'HWLOC', value_when_none='yes'),
+ tr(args.io_uring, 'IO_URING', value_when_none=None),
+ tr(args.alloc_failure_injection, 'ALLOC_FAILURE_INJECTION', value_when_none='DEFAULT'),
+ tr(args.task_backtrace, 'TASK_BACKTRACE'),
+ tr(args.alloc_page_size, 'ALLOC_PAGE_SIZE'),
+ tr(args.split_dwarf, 'SPLIT_DWARF'),
+ tr(args.heap_profiling, 'HEAP_PROFILING'),
+ tr(args.deferred_action_require_noexcept, 'DEFERRED_ACTION_REQUIRE_NOEXCEPT'),
+ tr(args.unused_result_error, 'UNUSED_RESULT_ERROR'),
+ tr(args.debug_shared_ptr, 'DEBUG_SHARED_PTR', value_when_none='default'),
+ ]
+
+ ingredients_to_cook = set(args.cook)
+
+ if args.dpdk:
+ ingredients_to_cook.add('dpdk')
+
+ # Generate a new build by pointing to the source directory.
+ if ingredients_to_cook:
+ # We need to use cmake-cooking for some dependencies.
+ inclusion_arguments = []
+
+ for ingredient in ingredients_to_cook:
+ inclusion_arguments.extend(['-i', ingredient])
+
+ ARGS = seastar_cmake.COOKING_BASIC_ARGS + inclusion_arguments
+ if args.user_cflags:
+ ARGS += ['-s', f'CXXFLAGS={args.user_cflags}']
+ if args.user_ldflags:
+ ARGS += ['-s', f'LDFLAGS={args.user_ldflags}']
+ ARGS += ['-d', BUILD_PATH, '--']
+ dir = seastar_cmake.ROOT_PATH
+ else:
+ # When building without cooked dependencies, we can invoke cmake directly. We can't call
+ # cooking.sh, because without any -i parameters, it will try to build
+ # everything.
+ ARGS = ['cmake', '-G', 'Ninja', '../..']
+ dir = BUILD_PATH
+ # filter out empty args, their values are actually "guess",
+ # CMake should be able to figure it out.
+ ARGS += filter(lambda arg: arg, TRANSLATED_ARGS)
+ if args.verbose:
+ print("Running CMake in '{}' ...".format(dir))
+ print(" \\\n ".join(ARGS))
+ os.makedirs(BUILD_PATH, exist_ok=True)
+ subprocess.check_call(ARGS, shell=False, cwd=dir)
+
+for mode in MODES:
+ configure_mode(mode)