[libcxx-commits] [libcxx] e0d0129 - [libc++] Allow building libc++ on platforms without a random device
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 15 09:20:58 PDT 2020
Author: Louis Dionne
Date: 2020-10-15T12:20:29-04:00
New Revision: e0d01294bc124211a8ffb55e69162eb34a242680
URL: https://github.com/llvm/llvm-project/commit/e0d01294bc124211a8ffb55e69162eb34a242680
DIFF: https://github.com/llvm/llvm-project/commit/e0d01294bc124211a8ffb55e69162eb34a242680.diff
LOG: [libc++] Allow building libc++ on platforms without a random device
Some platforms, like several embedded platforms, do not provide a source
of randomness through a random device. This commit makes it possible to
build and test libc++ for such platforms, i.e. without std::random_device.
Surprisingly, the only functionality that doesn't work on such platforms
is std::random_device itself -- everything else in <random> still works,
one just has to find alternative ways to seed the PRNGs.
Added:
libcxx/cmake/caches/Generic-no-random_device.cmake
libcxx/test/libcxx/numerics/rand/rand.device/has-no-random-device.verify.cpp
Modified:
libcxx/CMakeLists.txt
libcxx/include/__config_site.in
libcxx/include/random
libcxx/src/CMakeLists.txt
libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp
libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
libcxx/test/std/numerics/rand/rand.device/entropy.pass.cpp
libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
libcxx/test/support/filesystem_test_helper.h
libcxx/utils/ci/buildkite-pipeline.yml
libcxx/utils/ci/run-buildbot.sh
libcxx/utils/libcxx/test/features.py
Removed:
################################################################################
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index f67f417de238..69ff183770ad 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -109,6 +109,12 @@ option(LIBCXX_ENABLE_DEBUG_MODE_SUPPORT
By default, this is turned on. If you turn it off and try to enable the
debug mode when compiling a program against libc++, it will fail to link
since the required support isn't provided in the library." ON)
+option(LIBCXX_ENABLE_RANDOM_DEVICE
+ "Whether to include support for std::random_device in the library. Disabling
+ this can be useful when building the library for platforms that don't have
+ a source of randomness, such as some embedded platforms. When this is not
+ supported, most of <random> will still be available, but std::random_device
+ will not." ON)
option(LIBCXX_TEST_GDB_PRETTY_PRINTERS "Test gdb pretty printers." OFF)
set(LIBCXX_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/configs/legacy.cfg.in" CACHE STRING
"The Lit testing configuration to use when running the tests.")
@@ -836,6 +842,7 @@ config_define_if(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY _LIBCPP_HAS_THREAD_LIBRARY
config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC)
config_define_if(LIBCXX_NO_VCRUNTIME _LIBCPP_NO_VCRUNTIME)
config_define_if(LIBCXX_ENABLE_PARALLEL_ALGORITHMS _LIBCPP_HAS_PARALLEL_ALGORITHMS)
+config_define_if_not(LIBCXX_ENABLE_RANDOM_DEVICE _LIBCPP_HAS_NO_RANDOM_DEVICE)
if (LIBCXX_ABI_DEFINES)
set(abi_defines)
diff --git a/libcxx/cmake/caches/Generic-no-random_device.cmake b/libcxx/cmake/caches/Generic-no-random_device.cmake
new file mode 100644
index 000000000000..e9b4cc60cc80
--- /dev/null
+++ b/libcxx/cmake/caches/Generic-no-random_device.cmake
@@ -0,0 +1 @@
+set(LIBCXX_ENABLE_RANDOM_DEVICE OFF CACHE BOOL "")
diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in
index a6984b2eefc1..908fb1e674ce 100644
--- a/libcxx/include/__config_site.in
+++ b/libcxx/include/__config_site.in
@@ -32,6 +32,7 @@
#endif
#cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@
#cmakedefine _LIBCPP_HAS_PARALLEL_ALGORITHMS
+#cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE
@_LIBCPP_ABI_DEFINES@
diff --git a/libcxx/include/random b/libcxx/include/random
index ce3d135e064a..4321195c4f0e 100644
--- a/libcxx/include/random
+++ b/libcxx/include/random
@@ -3477,6 +3477,8 @@ typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
// random_device
+#if !defined(_LIBCPP_HAS_NO_RANDOM_DEVICE)
+
class _LIBCPP_TYPE_VIS random_device
{
#ifdef _LIBCPP_USING_DEV_RANDOM
@@ -3511,6 +3513,8 @@ private:
random_device& operator=(const random_device&); // = delete;
};
+#endif // !_LIBCPP_HAS_NO_RANDOM_DEVICE
+
// seed_seq
class _LIBCPP_TEMPLATE_VIS seed_seq
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index eab2152b5126..3c5bc1ebc576 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -27,7 +27,6 @@ set(LIBCXX_SOURCES
mutex_destructor.cpp
new.cpp
optional.cpp
- random.cpp
random_shuffle.cpp
regex.cpp
shared_mutex.cpp
@@ -61,6 +60,12 @@ if (LIBCXX_ENABLE_DEBUG_MODE_SUPPORT)
)
endif()
+if (LIBCXX_ENABLE_RANDOM_DEVICE)
+ list(APPEND LIBCXX_SOURCES
+ random.cpp
+ )
+endif()
+
if(WIN32)
list(APPEND LIBCXX_SOURCES
support/win32/locale_win32.cpp
diff --git a/libcxx/test/libcxx/numerics/rand/rand.device/has-no-random-device.verify.cpp b/libcxx/test/libcxx/numerics/rand/rand.device/has-no-random-device.verify.cpp
new file mode 100644
index 000000000000..66a3afb25645
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/rand/rand.device/has-no-random-device.verify.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure that std::random_device is not available in namespace std:: when
+// libc++ is built without support for random device.
+
+// REQUIRES: libcpp-has-no-random-device
+
+#include <random>
+
+int main(int, char**) {
+ std::random_device d; // expected-error {{no type named 'random_device' in namespace 'std'}}
+ return 0;
+}
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp
index d7bdbdb2de17..1f435840a24a 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp
@@ -19,7 +19,6 @@
#include "filesystem_include.h"
#include <cassert>
-#include <chrono>
#include <fstream>
#include <string>
@@ -31,14 +30,6 @@ using namespace fs;
TEST_SUITE(filesystem_copy_file_test_suite)
-static std::string random_hex_chars(uintmax_t size) {
- std::string data;
- data.reserve(size);
- for (uintmax_t I = 0; I < size; ++I)
- data.push_back(random_utils::random_hex_char());
- return data;
-}
-
// This test is intended to test 'sendfile's 2gb limit for a single call, and
// to ensure that libc++ correctly copies files larger than that limit.
// However it requires allocating ~5GB of filesystem space. This might not
@@ -58,12 +49,10 @@ TEST_CASE(large_file) {
TEST_UNSUPPORTED();
}
- // Use python to create a file right at the size limit.
+ // Create a file right at the size limit. The file is full of '\0's.
const path file = env.create_file("source", sendfile_size_limit);
- // Create some random data that looks
diff erent than the data before the
- // size limit.
- const std::string additional_data = random_hex_chars(additional_size);
- // Append this known data to the end of the source file.
+ const std::string additional_data(additional_size, 'x');
+ // Append known data to the end of the source file.
{
std::ofstream outf(file.native(), std::ios_base::app);
TEST_REQUIRE(outf.good());
diff --git a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
index b0d8605387d8..b12a7bb7598b 100644
--- a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
@@ -12,6 +12,8 @@
// XFAIL: with_system_cxx_lib=macosx10.10
// XFAIL: with_system_cxx_lib=macosx10.9
+// UNSUPPORTED: libcpp-has-no-random-device
+
// <random>
// class random_device;
diff --git a/libcxx/test/std/numerics/rand/rand.device/entropy.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/entropy.pass.cpp
index e93657c48722..4f09d05012ea 100644
--- a/libcxx/test/std/numerics/rand/rand.device/entropy.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.device/entropy.pass.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+// UNSUPPORTED: libcpp-has-no-random-device
+
// <random>
// class random_device;
diff --git a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
index d68c67a0a678..38522d8d87c1 100644
--- a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
@@ -12,6 +12,8 @@
// XFAIL: with_system_cxx_lib=macosx10.10
// XFAIL: with_system_cxx_lib=macosx10.9
+// UNSUPPORTED: libcpp-has-no-random-device
+
// <random>
// class random_device;
diff --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h
index 2a626f79daa4..448f9851293e 100644
--- a/libcxx/test/support/filesystem_test_helper.h
+++ b/libcxx/test/support/filesystem_test_helper.h
@@ -3,13 +3,12 @@
#include "filesystem_include.h"
-#include <sys/stat.h> // for mkdir, mkfifo
+#include <sys/stat.h> // for stat, mkdir, mkfifo
#include <unistd.h> // for ftruncate, link, symlink, getcwd, chdir
#include <cassert>
#include <cstdio> // for printf
#include <string>
-#include <random>
#include <chrono>
#include <vector>
#include <regex>
@@ -24,23 +23,25 @@
# include <sys/un.h>
#endif
-namespace random_utils {
-inline char to_hex(int ch) {
- return ch < 10 ? static_cast<char>('0' + ch)
- : static_cast<char>('a' + (ch - 10));
-}
-
-inline char random_hex_char() {
- static std::mt19937 rd{std::random_device{}()};
- static std::uniform_int_distribution<int> mrand{0, 15};
- return to_hex(mrand(rd));
-}
+namespace utils {
+ inline std::string getcwd() {
+ // Assume that path lengths are not greater than this.
+ // This should be fine for testing purposes.
+ char buf[4096];
+ char* ret = ::getcwd(buf, sizeof(buf));
+ assert(ret && "getcwd failed");
+ return std::string(ret);
+ }
-} // namespace random_utils
+ inline bool exists(std::string const& path) {
+ struct ::stat tmp;
+ return ::stat(path.c_str(), &tmp) == 0;
+ }
+} // end namespace utils
struct scoped_test_env
{
- scoped_test_env() : test_root(random_path()) {
+ scoped_test_env() : test_root(available_cwd_path()) {
std::string cmd = "mkdir -p " + test_root.native();
int ret = std::system(cmd.c_str());
assert(ret == 0);
@@ -174,20 +175,20 @@ struct scoped_test_env
fs::path test_root;
private:
- static std::string unique_path_suffix() {
- std::string model = "test.%%%%%%";
- for (auto & ch : model) {
- if (ch == '%')
- ch = random_utils::random_hex_char();
+ // This could potentially introduce a filesystem race if multiple
+ // scoped_test_envs were created concurrently in the same test (hence
+ // sharing the same cwd). However, it is fairly unlikely to happen as
+ // we generally don't use scoped_test_env from multiple threads, so
+ // this is deemed acceptable.
+ static inline fs::path available_cwd_path() {
+ fs::path const cwd = utils::getcwd();
+ fs::path const tmp = fs::temp_directory_path();
+ fs::path const base = tmp / cwd.filename();
+ int i = 0;
+ fs::path p = base / ("static_env." + std::to_string(i));
+ while (utils::exists(p)) {
+ p = fs::path(base) / ("static_env." + std::to_string(++i));
}
- return model;
- }
-
- // This could potentially introduce a filesystem race with other tests
- // running at the same time, but oh well, it's just test code.
- static inline fs::path random_path() {
- fs::path tmp = fs::temp_directory_path();
- fs::path p = fs::path(tmp) / unique_path_suffix();
return p;
}
};
@@ -301,15 +302,10 @@ class static_test_env {
};
struct CWDGuard {
- // Assume that path lengths are not greater than this.
- // This should be fine for testing purposes.
- char OldCWD[4096];
- CWDGuard() {
- char* ret = ::getcwd(OldCWD, sizeof(OldCWD));
- assert(ret && "getcwd failed");
- }
+ std::string oldCwd_;
+ CWDGuard() : oldCwd_(utils::getcwd()) { }
~CWDGuard() {
- int ret = ::chdir(OldCWD);
+ int ret = ::chdir(oldCwd_.c_str());
assert(ret == 0 && "chdir failed");
}
diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index 929ee98be464..6d416a36cba2 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -80,6 +80,11 @@ steps:
agents:
queue: "libcxx-builders"
+ - label: "No random device"
+ command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh generic-no-random_device | libcxx/utils/ci/phabricator-report"
+ agents:
+ queue: "libcxx-builders"
+
- label: "MacOS C++20"
command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh generic-cxx2a | libcxx/utils/ci/phabricator-report"
agents:
diff --git a/libcxx/utils/ci/run-buildbot.sh b/libcxx/utils/ci/run-buildbot.sh
index 279291d50888..87a1f0f1d622 100755
--- a/libcxx/utils/ci/run-buildbot.sh
+++ b/libcxx/utils/ci/run-buildbot.sh
@@ -109,6 +109,12 @@ generic-nodebug)
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
args+=("-C${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-nodebug.cmake")
;;
+generic-no-random_device)
+ export CC=clang
+ export CXX=clang++
+ args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
+ args+=("-C${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-random_device.cmake")
+;;
x86_64-apple-system)
export CC=clang
export CXX=clang++
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index dfdc0bae7a29..14d4dcb17943 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -73,7 +73,8 @@
'_LIBCPP_HAS_THREAD_API_PTHREAD': 'libcpp-has-thread-api-pthread',
'_LIBCPP_NO_VCRUNTIME': 'libcpp-no-vcruntime',
'_LIBCPP_ABI_VERSION': 'libcpp-abi-version',
- '_LIBCPP_ABI_UNSTABLE': 'libcpp-abi-unstable'
+ '_LIBCPP_ABI_UNSTABLE': 'libcpp-abi-unstable',
+ '_LIBCPP_HAS_NO_RANDOM_DEVICE': 'libcpp-has-no-random-device',
}
for macro, feature in macros.items():
DEFAULT_FEATURES += [
More information about the libcxx-commits
mailing list