diff options
Diffstat (limited to 'src/arrow/dev/archery/archery/lang/cpp.py')
-rw-r--r-- | src/arrow/dev/archery/archery/lang/cpp.py | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/src/arrow/dev/archery/archery/lang/cpp.py b/src/arrow/dev/archery/archery/lang/cpp.py new file mode 100644 index 000000000..c2b1ca680 --- /dev/null +++ b/src/arrow/dev/archery/archery/lang/cpp.py @@ -0,0 +1,296 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); 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 os + +from ..utils.cmake import CMakeDefinition + + +def truthifier(value): + return "ON" if value else "OFF" + + +def or_else(value, default): + return value if value else default + + +def coalesce(value, fallback): + return fallback if value is None else value + + +LLVM_VERSION = 7 + + +class CppConfiguration: + def __init__(self, + + # toolchain + cc=None, cxx=None, cxx_flags=None, + build_type=None, warn_level=None, + cpp_package_prefix=None, install_prefix=None, use_conda=None, + build_static=False, build_shared=True, build_unity=True, + # tests & examples + with_tests=None, with_benchmarks=None, with_examples=None, + with_integration=None, + # static checks + use_asan=None, use_tsan=None, use_ubsan=None, + with_fuzzing=None, + # Components + with_compute=None, with_csv=None, with_cuda=None, + with_dataset=None, with_filesystem=None, with_flight=None, + with_gandiva=None, with_hdfs=None, with_hiveserver2=None, + with_ipc=True, with_json=None, with_jni=None, + with_mimalloc=None, + with_parquet=None, with_plasma=None, with_python=True, + with_r=None, with_s3=None, + # Compressions + with_brotli=None, with_bz2=None, with_lz4=None, + with_snappy=None, with_zlib=None, with_zstd=None, + # extras + with_lint_only=False, + use_gold_linker=True, + simd_level="SSE4_2", + cmake_extras=None): + self._cc = cc + self._cxx = cxx + self.cxx_flags = cxx_flags + + self._build_type = build_type + self.warn_level = warn_level + self._install_prefix = install_prefix + self._package_prefix = cpp_package_prefix + self._use_conda = use_conda + self.build_static = build_static + self.build_shared = build_shared + self.build_unity = build_unity + + self.with_tests = with_tests + self.with_benchmarks = with_benchmarks + self.with_examples = with_examples + self.with_integration = with_integration + + self.use_asan = use_asan + self.use_tsan = use_tsan + self.use_ubsan = use_ubsan + self.with_fuzzing = with_fuzzing + + self.with_compute = with_compute + self.with_csv = with_csv + self.with_cuda = with_cuda + self.with_dataset = with_dataset + self.with_filesystem = with_filesystem + self.with_flight = with_flight + self.with_gandiva = with_gandiva + self.with_hdfs = with_hdfs + self.with_hiveserver2 = with_hiveserver2 + self.with_ipc = with_ipc + self.with_json = with_json + self.with_jni = with_jni + self.with_mimalloc = with_mimalloc + self.with_parquet = with_parquet + self.with_plasma = with_plasma + self.with_python = with_python + self.with_r = with_r + self.with_s3 = with_s3 + + self.with_brotli = with_brotli + self.with_bz2 = with_bz2 + self.with_lz4 = with_lz4 + self.with_snappy = with_snappy + self.with_zlib = with_zlib + self.with_zstd = with_zstd + + self.with_lint_only = with_lint_only + self.use_gold_linker = use_gold_linker + self.simd_level = simd_level + + self.cmake_extras = cmake_extras + + # Fixup required dependencies by providing sane defaults if the caller + # didn't specify the option. + if self.with_r: + self.with_csv = coalesce(with_csv, True) + self.with_dataset = coalesce(with_dataset, True) + self.with_filesystem = coalesce(with_filesystem, True) + self.with_ipc = coalesce(with_ipc, True) + self.with_json = coalesce(with_json, True) + self.with_parquet = coalesce(with_parquet, True) + + if self.with_python: + self.with_zlib = coalesce(with_zlib, True) + self.with_lz4 = coalesce(with_lz4, True) + + if self.with_dataset: + self.with_filesystem = coalesce(with_filesystem, True) + self.with_parquet = coalesce(with_parquet, True) + + if self.with_parquet: + self.with_snappy = coalesce(with_snappy, True) + + @property + def build_type(self): + if self._build_type: + return self._build_type + + if self.with_fuzzing: + return "relwithdebinfo" + + return "release" + + @property + def cc(self): + if self._cc: + return self._cc + + if self.with_fuzzing: + return "clang-{}".format(LLVM_VERSION) + + return None + + @property + def cxx(self): + if self._cxx: + return self._cxx + + if self.with_fuzzing: + return "clang++-{}".format(LLVM_VERSION) + + return None + + def _gen_defs(self): + if self.cxx_flags: + yield ("ARROW_CXXFLAGS", self.cxx_flags) + + yield ("CMAKE_EXPORT_COMPILE_COMMANDS", truthifier(True)) + yield ("CMAKE_BUILD_TYPE", self.build_type) + + if not self.with_lint_only: + yield ("BUILD_WARNING_LEVEL", + or_else(self.warn_level, "production")) + + # if not ctx.quiet: + # yield ("ARROW_VERBOSE_THIRDPARTY_BUILD", "ON") + + maybe_prefix = self.install_prefix + if maybe_prefix: + yield ("CMAKE_INSTALL_PREFIX", maybe_prefix) + + if self._package_prefix is not None: + yield ("ARROW_DEPENDENCY_SOURCE", "SYSTEM") + yield ("ARROW_PACKAGE_PREFIX", self._package_prefix) + + yield ("ARROW_BUILD_STATIC", truthifier(self.build_static)) + yield ("ARROW_BUILD_SHARED", truthifier(self.build_shared)) + yield ("CMAKE_UNITY_BUILD", truthifier(self.build_unity)) + + # Tests and benchmarks + yield ("ARROW_BUILD_TESTS", truthifier(self.with_tests)) + yield ("ARROW_BUILD_BENCHMARKS", truthifier(self.with_benchmarks)) + yield ("ARROW_BUILD_EXAMPLES", truthifier(self.with_examples)) + yield ("ARROW_BUILD_INTEGRATION", truthifier(self.with_integration)) + + # Static checks + yield ("ARROW_USE_ASAN", truthifier(self.use_asan)) + yield ("ARROW_USE_TSAN", truthifier(self.use_tsan)) + yield ("ARROW_USE_UBSAN", truthifier(self.use_ubsan)) + yield ("ARROW_FUZZING", truthifier(self.with_fuzzing)) + + # Components + yield ("ARROW_COMPUTE", truthifier(self.with_compute)) + yield ("ARROW_CSV", truthifier(self.with_csv)) + yield ("ARROW_CUDA", truthifier(self.with_cuda)) + yield ("ARROW_DATASET", truthifier(self.with_dataset)) + yield ("ARROW_FILESYSTEM", truthifier(self.with_filesystem)) + yield ("ARROW_FLIGHT", truthifier(self.with_flight)) + yield ("ARROW_GANDIVA", truthifier(self.with_gandiva)) + yield ("ARROW_PARQUET", truthifier(self.with_parquet)) + yield ("ARROW_HDFS", truthifier(self.with_hdfs)) + yield ("ARROW_HIVESERVER2", truthifier(self.with_hiveserver2)) + yield ("ARROW_IPC", truthifier(self.with_ipc)) + yield ("ARROW_JSON", truthifier(self.with_json)) + yield ("ARROW_JNI", truthifier(self.with_jni)) + yield ("ARROW_MIMALLOC", truthifier(self.with_mimalloc)) + yield ("ARROW_PLASMA", truthifier(self.with_plasma)) + yield ("ARROW_PYTHON", truthifier(self.with_python)) + yield ("ARROW_S3", truthifier(self.with_s3)) + + # Compressions + yield ("ARROW_WITH_BROTLI", truthifier(self.with_brotli)) + yield ("ARROW_WITH_BZ2", truthifier(self.with_bz2)) + yield ("ARROW_WITH_LZ4", truthifier(self.with_lz4)) + yield ("ARROW_WITH_SNAPPY", truthifier(self.with_snappy)) + yield ("ARROW_WITH_ZLIB", truthifier(self.with_zlib)) + yield ("ARROW_WITH_ZSTD", truthifier(self.with_zstd)) + + yield ("ARROW_LINT_ONLY", truthifier(self.with_lint_only)) + + # Some configurations don't like gnu gold linker. + broken_with_gold_ld = [self.with_fuzzing, self.with_gandiva] + if self.use_gold_linker and not any(broken_with_gold_ld): + yield ("ARROW_USE_LD_GOLD", truthifier(self.use_gold_linker)) + yield ("ARROW_SIMD_LEVEL", or_else(self.simd_level, "SSE4_2")) + + # Detect custom conda toolchain + if self.use_conda: + for d, v in [('CMAKE_AR', 'AR'), ('CMAKE_RANLIB', 'RANLIB')]: + v = os.environ.get(v) + if v: + yield (d, v) + + @property + def install_prefix(self): + if self._install_prefix: + return self._install_prefix + + if self.use_conda: + return os.environ.get("CONDA_PREFIX") + + return None + + @property + def use_conda(self): + # If the user didn't specify a preference, guess via environment + if self._use_conda is None: + return os.environ.get("CONDA_PREFIX") is not None + + return self._use_conda + + @property + def definitions(self): + extras = list(self.cmake_extras) if self.cmake_extras else [] + definitions = ["-D{}={}".format(d[0], d[1]) for d in self._gen_defs()] + return definitions + extras + + @property + def environment(self): + env = os.environ.copy() + + if self.cc: + env["CC"] = self.cc + + if self.cxx: + env["CXX"] = self.cxx + + return env + + +class CppCMakeDefinition(CMakeDefinition): + def __init__(self, source, conf, **kwargs): + self.configuration = conf + super().__init__(source, **kwargs, + definitions=conf.definitions, env=conf.environment, + build_type=conf.build_type) |