This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 204eca6591b [bugfix](glibc) fix glibc compatible bugs (#67701)
204eca6591b is described below
commit 204eca6591b0d62c5349295394f33f4be2dc4dfb
Author: yiguolei <[email protected]>
AuthorDate: Thu Sep 10 07:31:50 2026 +0800
[bugfix](glibc) fix glibc compatible bugs (#67701)
### What problem does this PR solve?
Rust std weak-links this glibc 2.18 entry point and has an internal
fallback when it is absent. Since the LDB sysroot exposes it, the final
linker would otherwise record GLIBC_2.18.
See https://github.com/rust-lang/rust/issues/57497 for more details.
I have checked the output.
objdump -T output/be/lib/doris_be | grep -o 'GLIBC_[0-9.]*' | sort -Vu |
tail
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
Related PR: #xxx
Problem Summary:
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [ ] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
be/AGENTS.md | 54 ++++++++++
be/CMakeLists.txt | 10 ++
be/cmake/check_glibc_compatibility.cmake | 70 +++++++++++++
be/src/glibc-compatibility/lance_symbol_versions.c | 115 ++++++++++++++++++++-
be/src/glibc-compatibility/musl/expf.c | 80 ++++++++++++++
be/src/service/CMakeLists.txt | 44 +++++---
6 files changed, 356 insertions(+), 17 deletions(-)
diff --git a/be/AGENTS.md b/be/AGENTS.md
index 497d8a10eda..58b4e4a54f4 100644
--- a/be/AGENTS.md
+++ b/be/AGENTS.md
@@ -68,3 +68,57 @@ past a gate is never to bypass it, but one of:
skip entry present?
- [ ] `git grep` for a deleted/renamed header in skip lists and gate tables:
stale entries fail configure loudly — fix them in the same PR.
+
+## Preserve the glibc 2.17 runtime baseline
+
+Treat glibc 2.17 compatibility as part of the ABI contract of a production
Doris BE release.
+The final `doris_be` executable and the shared libraries shipped with it must
not contain an
+undefined symbol-version requirement newer than `GLIBC_2.17` on any supported
architecture.
+A successful build on a newer Linux distribution is not sufficient evidence of
compatibility.
+
+The 2.17 baseline is specifically required for CentOS 7, which ships glibc
2.17 and still has a
+large Doris deployment base. Do not dismiss a `GLIBC_2.18` requirement as a
minor version increase:
+the CentOS 7 dynamic loader cannot satisfy it, so `doris_be` fails during
process startup before any
+application-level fallback can run. Requiring even one `GLIBC_2.18` symbol
therefore drops CentOS 7
+compatibility and is a release-blocking regression.
+
+Apply this requirement when reviewing changes to BE source code, CMake or
linker options, the LDB
+toolchain/sysroot, third-party libraries, Rust crates or static archives, and
+`be/src/glibc-compatibility/`. A sysroot helps constrain symbol selection, but
it does not by itself
+guarantee the final ABI: an archive built against newer headers/libraries or a
symbol resolved from
+the wrong library or in the wrong link order can still add a newer GLIBC
requirement.
+
+For every relevant release build, inspect the completed ELF artifacts rather
than only their
+individual inputs. At minimum, audit `doris_be` with one of the following and
investigate every
+version greater than 2.17:
+
+```shell
+objdump -T path/to/doris_be \
+ | grep -oE 'GLIBC_[0-9]+(\.[0-9]+)*' \
+ | sort -Vu
+
+readelf --version-info --wide path/to/doris_be
+```
+
+Use `objdump -T path/to/doris_be | grep GLIBC_...` or `readelf --dyn-syms
--wide` to identify the
+specific undefined symbols. Repeat the audit for shipped BE shared libraries;
a clean executable
+does not make a bundled library with a newer requirement safe. When a glibc
2.17 environment is
+available, also start and exercise the release artifact there.
+
+Known accidental bindings that deserve explicit attention include `logf`,
`log2f`, and `expf` at
+`GLIBC_2.27`, `copy_file_range` at `GLIBC_2.27`, `strfromf128` at
`GLIBC_2.26`, and
+`__cxa_thread_atexit_impl` at `GLIBC_2.18`. These version tags describe what
the final binary asks
+the dynamic loader to provide; they do not necessarily mean that the
underlying API was first
+created in that glibc release.
+
+When a dependency needs a post-2.17 libc API, use an existing Doris
compatibility implementation
+or add a narrowly scoped implementation with matching semantics. If a raw
syscall is appropriate,
+preserve the caller's expected `ENOSYS` or other fallback behavior on old
kernels. If a compatible
+definition lives in a static archive or object library, ensure the final link
actually extracts and
+binds that definition; verify this in the completed ELF symbol table. Do not
treat an implementation
+present in an archive as proof that it was selected.
+
+Do not solve a compatibility regression by bundling a newer glibc, changing
`LD_LIBRARY_PATH` to a
+private libc, or allowing host include/library paths to leak into the build.
Such changes can mix an
+incompatible loader, libc, and NSS/runtime components. Fix the build input,
symbol implementation,
+or link selection, then repeat the final-artifact audit.
diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt
index c36a822d942..c03a5e0c8bf 100644
--- a/be/CMakeLists.txt
+++ b/be/CMakeLists.txt
@@ -855,7 +855,17 @@ if (GLIBC_COMPATIBILITY)
# Keep lance_c here instead of COMMON_THIRDPARTY: placing its required
libm there
# would resolve -lm symbol before Doris compatibility is scanned,
preventing
# the linker from selecting Doris' optimized implementations.
+ # lance_c can also introduce single-precision math references after the
+ # compatibility archive has already been scanned. As ClickHouse does for
its
+ # compatibility archive, force the GLIBC_2.27 math symbols to be undefined
up
+ # front so the linker extracts Doris' musl implementations instead of
binding
+ # late references to the toolchain's libm.
set(DORIS_LINK_LIBS ${DORIS_LINK_LIBS}
+ -Wl,-u,logf
+ -Wl,-u,powf
+ -Wl,-u,expf
+ -Wl,-u,exp2f
+ -Wl,-u,log2f
glibc-compatibility-explicit
glibc-compatibility
-lm
diff --git a/be/cmake/check_glibc_compatibility.cmake
b/be/cmake/check_glibc_compatibility.cmake
new file mode 100644
index 00000000000..435419bf07d
--- /dev/null
+++ b/be/cmake/check_glibc_compatibility.cmake
@@ -0,0 +1,70 @@
+# 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.
+
+if (NOT DEFINED ARTIFACT OR NOT EXISTS "${ARTIFACT}")
+ message(FATAL_ERROR "Cannot check glibc compatibility: '${ARTIFACT}' does
not exist")
+endif()
+
+if (NOT DEFINED BASELINE OR BASELINE STREQUAL "")
+ message(FATAL_ERROR "Cannot check glibc compatibility: BASELINE is not
set")
+endif()
+
+if (NOT DEFINED OBJDUMP OR OBJDUMP STREQUAL "" OR NOT EXISTS "${OBJDUMP}")
+ find_program(OBJDUMP NAMES objdump llvm-objdump REQUIRED)
+endif()
+
+execute_process(
+ COMMAND "${OBJDUMP}" -T "${ARTIFACT}"
+ RESULT_VARIABLE objdump_result
+ OUTPUT_VARIABLE dynamic_symbol_table
+ ERROR_VARIABLE objdump_error)
+
+if (NOT objdump_result EQUAL 0)
+ message(FATAL_ERROR
+ "Cannot read the dynamic symbol table from '${ARTIFACT}':
${objdump_error}")
+endif()
+
+string(REPLACE "\n" ";" dynamic_symbol_lines "${dynamic_symbol_table}")
+set(incompatible_symbols)
+
+foreach (symbol_line IN LISTS dynamic_symbol_lines)
+ # Only undefined symbols are runtime requirements on the target system.
+ if (symbol_line MATCHES "\\*UND\\*")
+ string(REGEX MATCH "GLIBC_[0-9]+(\\.[0-9]+)+" symbol_version
"${symbol_line}")
+ if (NOT "${symbol_version}" STREQUAL "")
+ string(REGEX REPLACE "^GLIBC_" "" numeric_version
"${symbol_version}")
+ if ("${numeric_version}" VERSION_GREATER "${BASELINE}")
+ string(REGEX MATCH "[^ \t]+$" symbol_name "${symbol_line}")
+ list(APPEND incompatible_symbols "${symbol_version}
${symbol_name}")
+ endif()
+ endif()
+ endif()
+endforeach()
+
+if (NOT "${incompatible_symbols}" STREQUAL "")
+ list(REMOVE_DUPLICATES incompatible_symbols)
+ list(SORT incompatible_symbols)
+ string(JOIN "\n " formatted_symbols ${incompatible_symbols})
+ message(FATAL_ERROR
+ "${ARTIFACT} requires glibc symbols newer than GLIBC_${BASELINE}:\n"
+ " ${formatted_symbols}\n"
+ "The production BE must remain runnable on CentOS 7 (glibc
${BASELINE}).")
+endif()
+
+message(STATUS
+ "glibc compatibility check passed: ${ARTIFACT} requires no symbols newer
than "
+ "GLIBC_${BASELINE}")
diff --git a/be/src/glibc-compatibility/lance_symbol_versions.c
b/be/src/glibc-compatibility/lance_symbol_versions.c
index b0594dce06b..66b9cdae5cb 100644
--- a/be/src/glibc-compatibility/lance_symbol_versions.c
+++ b/be/src/glibc-compatibility/lance_symbol_versions.c
@@ -18,8 +18,12 @@
#define _GNU_SOURCE
#include <fcntl.h>
+#include <pthread.h>
#include <spawn.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
#include <sys/uio.h>
+#include <unistd.h>
#if defined(__x86_64__)
#define DORIS_GLIBC_BASE_VERSION "GLIBC_2.2.5"
@@ -41,6 +45,76 @@
// glibc symbol, so it cannot recurse back into the hidden wrapper.
#define DORIS_HIDDEN __attribute__((visibility("hidden")))
+typedef void (*doris_tls_destructor)(void*);
+
+struct doris_tls_destructor_entry {
+ doris_tls_destructor destructor;
+ void* object;
+ struct doris_tls_destructor_entry* next;
+};
+
+static pthread_key_t doris_tls_destructor_key;
+static pthread_once_t doris_tls_destructor_once = PTHREAD_ONCE_INIT;
+
+static void doris_run_tls_destructors(void* value) {
+ struct doris_tls_destructor_entry* entry = value;
+ while (entry != NULL) {
+ struct doris_tls_destructor_entry* next = entry->next;
+ doris_tls_destructor destructor = entry->destructor;
+ void* object = entry->object;
+
+ // Publish the remainder before invoking the destructor. A destructor
+ // may register another TLS destructor, which must run before the older
+ // entries that are still pending.
+ if (pthread_setspecific(doris_tls_destructor_key, next) != 0) {
+ abort();
+ }
+ free(entry);
+ destructor(object);
+ entry = pthread_getspecific(doris_tls_destructor_key);
+ }
+}
+
+static void doris_run_main_thread_tls_destructors(void) {
+ doris_run_tls_destructors(pthread_getspecific(doris_tls_destructor_key));
+}
+
+static void doris_init_tls_destructor_key(void) {
+ if (pthread_key_create(&doris_tls_destructor_key,
doris_run_tls_destructors) != 0) {
+ abort();
+ }
+ // pthread_key_create() arranges for doris_run_tls_destructors() to be
+ // called automatically when an ordinary worker thread exits. However,
+ // returning from main() (which is equivalent to exit()) does not run the
+ // initial thread's pthread key destructors. Register an atexit handler so
+ // TLS destructors belonging to the thread that performs normal process
+ // termination are still invoked.
+ //
+ // This relies on Doris normally terminating the process from its initial
+ // thread. If another thread calls exit(), atexit handlers execute in that
+ // thread and pthread_getspecific() observes that thread's TLS state.
+ // atexit handlers are not invoked by abort(), _exit(), fatal signals, or
+ // SIGKILL; those paths are already abnormal process termination.
+ //
+ // Unlike glibc, this fallback puts the initial thread's TLS cleanup in the
+ // same LIFO list as atexit callbacks and static-object destructors. A
static
+ // object initialized after this handler is registered is therefore
destroyed
+ // before the TLS objects. We accept this limitation because Doris normally
+ // terminates with _exit(), and normal destructor processing is currently
used
+ // only when enable_graceful_exit_check is enabled for sanitizer leak
checks.
+ // TLS destructors on that diagnostic path must not access static-lifetime
+ // objects that may already have been destroyed. If graceful exit becomes a
+ // production path, the initial thread's TLS destructors must instead be
run
+ // explicitly before the atexit/static-destructor list.
+ //
+ // A registration failure means that normal main-thread TLS cleanup cannot
+ // be guaranteed, so fail immediately instead of continuing with a
partially
+ // installed compatibility implementation.
+ if (atexit(doris_run_main_thread_tls_destructors) != 0) {
+ abort();
+ }
+}
+
extern __typeof__(posix_spawnp) __doris_old_posix_spawnp;
DORIS_GLIBC_SYMVER(__doris_old_posix_spawnp, posix_spawnp,
DORIS_GLIBC_BASE_VERSION);
@@ -53,8 +127,8 @@
DORIS_GLIBC_SYMVER(__doris_old_posix_spawn_file_actions_destroy, posix_spawn_fil
DORIS_GLIBC_BASE_VERSION);
extern __typeof__(posix_spawn_file_actions_adddup2)
__doris_old_posix_spawn_file_actions_adddup2;
-DORIS_GLIBC_SYMVER(__doris_old_posix_spawn_file_actions_adddup2,
- posix_spawn_file_actions_adddup2, DORIS_GLIBC_BASE_VERSION);
+DORIS_GLIBC_SYMVER(__doris_old_posix_spawn_file_actions_adddup2,
posix_spawn_file_actions_adddup2,
+ DORIS_GLIBC_BASE_VERSION);
extern __typeof__(preadv) __doris_old_preadv;
DORIS_GLIBC_SYMVER(__doris_old_preadv, preadv, DORIS_GLIBC_PREADV_VERSION);
@@ -90,3 +164,40 @@ DORIS_HIDDEN ssize_t splice(int fd_in, off64_t* offset_in,
int fd_out, off64_t*
size_t length, unsigned int flags) {
return __doris_old_splice(fd_in, offset_in, fd_out, offset_out, length,
flags);
}
+
+// Rust std weak-links copy_file_range and otherwise issues the syscall itself.
+// Provide that syscall path locally so linking on glibc 2.27 does not attach a
+// GLIBC_2.27 version requirement. Old kernels return ENOSYS and Rust falls
back
+// to its generic copy loop.
+DORIS_HIDDEN ssize_t copy_file_range(int fd_in, off64_t* offset_in, int
fd_out, off64_t* offset_out,
+ size_t length, unsigned int flags) {
+ return (ssize_t)syscall(SYS_copy_file_range, fd_in, offset_in, fd_out,
offset_out, length,
+ flags);
+}
+
+// Rust std weak-links this glibc 2.18 entry point and has an internal fallback
+// when it is absent. Since the LDB sysroot exposes it, the final linker would
+// otherwise record GLIBC_2.18. Supply equivalent pthread-key based
registration
+// locally. All callers are linked into doris_be, so dso_symbol tracking for
+// dlclose is intentionally unnecessary.
+// See https://github.com/rust-lang/rust/issues/57497 for more details.
+DORIS_HIDDEN int __cxa_thread_atexit_impl(doris_tls_destructor destructor,
void* object,
+ void* dso_symbol) {
+ (void)dso_symbol;
+ if (pthread_once(&doris_tls_destructor_once,
doris_init_tls_destructor_key) != 0) {
+ abort();
+ }
+
+ struct doris_tls_destructor_entry* entry = malloc(sizeof(*entry));
+ if (entry == NULL) {
+ abort();
+ }
+ entry->destructor = destructor;
+ entry->object = object;
+ entry->next = pthread_getspecific(doris_tls_destructor_key);
+ if (pthread_setspecific(doris_tls_destructor_key, entry) != 0) {
+ free(entry);
+ abort();
+ }
+ return 0;
+}
diff --git a/be/src/glibc-compatibility/musl/expf.c
b/be/src/glibc-compatibility/musl/expf.c
new file mode 100644
index 00000000000..f9fbf8e727d
--- /dev/null
+++ b/be/src/glibc-compatibility/musl/expf.c
@@ -0,0 +1,80 @@
+/*
+ * Single-precision e^x function.
+ *
+ * Copyright (c) 2017-2018, Arm Limited.
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "libm.h"
+#include "exp2f_data.h"
+
+/*
+EXP2F_TABLE_BITS = 5
+EXP2F_POLY_ORDER = 3
+
+ULP error: 0.502 (nearest rounding.)
+Relative error: 1.69 * 2^-34 in [-ln2/64, ln2/64] (before rounding.)
+Wrong count: 170635 (all nearest rounding wrong results with fma.)
+Non-nearest ULP error: 1 (rounded ULP error)
+*/
+
+#define N (1 << EXP2F_TABLE_BITS)
+#define InvLn2N __exp2f_data.invln2_scaled
+#define T __exp2f_data.tab
+#define C __exp2f_data.poly_scaled
+
+static inline uint32_t top12(float x)
+{
+ return asuint(x) >> 20;
+}
+
+float expf(float x)
+{
+ uint32_t abstop;
+ uint64_t ki, t;
+ double_t kd, xd, z, r, r2, y, s;
+
+ xd = (double_t)x;
+ abstop = top12(x) & 0x7ff;
+ if (predict_false(abstop >= top12(88.0f))) {
+ /* |x| >= 88 or x is nan. */
+ if (asuint(x) == asuint(-INFINITY))
+ return 0.0f;
+ if (abstop >= top12(INFINITY))
+ return x + x;
+ if (x > 0x1.62e42ep6f) /* x > log(0x1p128) ~= 88.72 */
+ return __math_oflowf(0);
+ if (x < -0x1.9fe368p6f) /* x < log(0x1p-150) ~= -103.97 */
+ return __math_uflowf(0);
+ }
+
+ /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k. */
+ z = InvLn2N * xd;
+
+ /* Round and convert z to int, the result is in [-150*N, 128*N] and
+ ideally ties-to-even rule is used, otherwise the magnitude of r
+ can be bigger which gives larger approximation error. */
+#if TOINT_INTRINSICS
+ kd = roundtoint(z);
+ ki = converttoint(z);
+#else
+# define SHIFT __exp2f_data.shift
+ kd = eval_as_double(z + SHIFT);
+ ki = asuint64(kd);
+ kd -= SHIFT;
+#endif
+ r = z - kd;
+
+ /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
+ t = T[ki % N];
+ t += ki << (52 - EXP2F_TABLE_BITS);
+ s = asdouble(t);
+ z = C[0] * r + C[1];
+ r2 = r * r;
+ y = C[2] * r + 1;
+ y = z * r2 + y;
+ y = y * s;
+ return eval_as_float(y);
+}
diff --git a/be/src/service/CMakeLists.txt b/be/src/service/CMakeLists.txt
index f07b896d4a4..be7a01be5b2 100644
--- a/be/src/service/CMakeLists.txt
+++ b/be/src/service/CMakeLists.txt
@@ -64,21 +64,18 @@ if (${MAKE_TEST} STREQUAL "OFF" AND ${BUILD_BENCHMARK}
STREQUAL "OFF")
endif ()
pch_reuse(doris_be)
- # This permits libraries loaded by dlopen to link to the symbols in the
program.
- set_target_properties(doris_be PROPERTIES ENABLE_EXPORTS 1)
-
- # ...but not the symbols of the RocksDB we link statically. Exporting
those makes this
- # executable the definition every later-loaded library binds to, and a JNI
library that
- # carries its own RocksDB then runs half on ours: the fluss scanner
bundles frocksdbjni,
- # whose librocksdbjni.so defines 2576 rocksdb symbols under names
identical to ours but
- # was built against the pre-C++11 libstdc++ string ABI. Objects laid out
by one and used
- # by the other yield a garbage length, an std::bad_alloc that escapes the
JNI frame, and
- # an aborted BE. Hiding this archive lets that library bind to its own
copy.
- #
- # Scoped to the archive rather than dropping ENABLE_EXPORTS: what needs
the exports is
- # native UDFs (runtime/user_function_cache.cpp dlopens them), and those
use the Doris UDF
- # ABI, which has nothing to do with RocksDB. Crash stacks do not need it
either -- they are
- # symbolized from debug info, which is why they name even
anonymous-namespace functions.
+ # Keep doris_be symbols private. Java UDF callbacks are registered
explicitly through JNI and
+ # Python UDFs run out of process, so neither requires executable exports.
Exporting all symbols
+ # would also let dlopened libraries bind to private copies from static
dependencies.
+
+ # Keep the symbols of the RocksDB we link statically out of the dynamic
symbol table. Making
+ # them visible would make this executable the definition every
later-loaded library binds to.
+ # A JNI library that carries its own RocksDB would then run half on ours:
the fluss scanner
+ # bundles frocksdbjni, whose librocksdbjni.so defines 2576 rocksdb symbols
under names
+ # identical to ours but was built against the pre-C++11 libstdc++ string
ABI. Objects laid out
+ # by one implementation and used by the other yield a garbage length, an
std::bad_alloc that
+ # escapes the JNI frame, and an aborted BE. Hiding this archive lets that
library bind to its
+ # own copy.
#
# The same library also duplicates zstd, lz4, snappy, bzip2 and zlib
symbols. Those are C
# ABIs, stable across versions and layout-free, so they are left alone
until something
@@ -95,6 +92,23 @@ if (${MAKE_TEST} STREQUAL "OFF" AND ${BUILD_BENCHMARK}
STREQUAL "OFF")
${DORIS_LINK_LIBS}
)
+ if (OS_LINUX AND GLIBC_COMPATIBILITY)
+ # Use TARGET_FILE rather than an install/output directory so this check
+ # follows doris_be if its build location or output name changes.
+ set(GLIBC_COMPATIBILITY_CHECK
+ "${BASE_DIR}/cmake/check_glibc_compatibility.cmake")
+ set_property(TARGET doris_be APPEND PROPERTY LINK_DEPENDS
+ "${GLIBC_COMPATIBILITY_CHECK}")
+ add_custom_command(TARGET doris_be POST_BUILD
+ COMMAND "${CMAKE_COMMAND}"
+ "-DARTIFACT=$<TARGET_FILE:doris_be>"
+ "-DOBJDUMP=${CMAKE_OBJDUMP}"
+ "-DBASELINE=2.17"
+ -P "${GLIBC_COMPATIBILITY_CHECK}"
+ COMMENT "Checking that doris_be requires no glibc symbols newer
than GLIBC_2.17"
+ VERBATIM)
+ endif()
+
install(DIRECTORY DESTINATION ${OUTPUT_DIR}/lib/)
install(TARGETS doris_be DESTINATION ${OUTPUT_DIR}/lib/)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]