summaryrefslogtreecommitdiffstats
path: root/src/seastar/configure.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xsrc/seastar/configure.py232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/seastar/configure.py b/src/seastar/configure.py
new file mode 100755
index 000000000..4e2be72b4
--- /dev/null
+++ b/src/seastar/configure.py
@@ -0,0 +1,232 @@
+#!/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 distutils.dir_util
+import os
+import seastar_cmake
+import subprocess
+import sys
+import tempfile
+
+tempfile.tempdir = "./build/tmp"
+
+def add_tristate(arg_parser, name, dest, help):
+ arg_parser.add_argument('--enable-' + name, dest = dest, action = 'store_true', default = None,
+ help = 'Enable ' + help)
+ 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:
+ ofile = tempfile.mktemp()
+ 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 dialect_supported(dialect, compiler='g++'):
+ return try_compile(compiler=compiler, source='', flags=['-std=' + dialect])
+
+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++-dialect', action='store', dest='cpp_dialect', default='',
+ help='C++ dialect 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.')
+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')
+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('--heap-profiling', dest='heap_profiling', action='store_true', default=False, help='Enable heap profiling')
+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_dialect(dialects, compiler):
+ """Returns the first C++ dialect accepted by the compiler in the sequence,
+ assuming the "best" dialects appear first.
+
+ If no dialects are accepted, the result is the last dialect in the sequence
+ (we assume that this error will be displayed to the user - during compile
+ time - in an informative way).
+
+ """
+ for d in dialects:
+ if dialect_supported(d, compiler):
+ return d
+
+ return d
+
+if args.cpp_dialect == '':
+ cpp_dialects = ['gnu++17', 'gnu++1z', 'gnu++14', 'gnu++1y']
+ args.cpp_dialect = identify_best_dialect(cpp_dialects, 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_INSTALL_PREFIX={}'.format(args.install_prefix),
+ '-DSeastar_API_LEVEL={}'.format(args.api_level),
+ 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.cpp_dialect, 'CXX_DIALECT'),
+ tr(args.dpdk, 'DPDK'),
+ tr(infer_dpdk_machine(args.user_cflags), 'DPDK_MACHINE'),
+ tr(args.hwloc, 'HWLOC', value_when_none='yes'),
+ 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.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 + ['-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
+ ARGS += TRANSLATED_ARGS
+ if args.verbose:
+ print("Running CMake in '{}' ...".format(dir))
+ print(" \\\n ".join(ARGS))
+ distutils.dir_util.mkpath(BUILD_PATH)
+ subprocess.check_call(ARGS, shell=False, cwd=dir)
+
+for mode in MODES:
+ configure_mode(mode)