This patch adds targets for printf and fprintf to the bazel build.
Additionally, it adds support for the build system to specify where
files should be written for testing purposes. This was necessary to
enable the fprintf test under bazel.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D147008
)
add_header_library(
+ c_string
+ HDRS
+ c_string.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.CPP.string
+)
+
+add_header_library(
ctype_utils
HDRS
ctype_utils.h
--- /dev/null
+//===-- Implementation of a struct to hold a string in menory -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_C_STRING_H
+#define LLVM_LIBC_SRC_SUPPORT_C_STRING_H
+
+#include "src/__support/CPP/string.h"
+#include "src/__support/macros/attributes.h" // for LIBC_INLINE
+
+namespace __llvm_libc {
+
+// The CString class is a companion to the cpp::string class. Its use case is as
+// a return value for a function that in C would return a char* and a flag for
+// if that char* needs to be freed.
+class CString {
+ cpp::string str;
+
+public:
+ // These constructors can be implemented iff required.
+ CString() = delete;
+ CString(const CString &) = delete;
+ CString(CString &&) = delete;
+
+ LIBC_INLINE CString(cpp::string in_str) : str(in_str) {}
+
+ LIBC_INLINE operator const char *() const { return str.c_str(); }
+};
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_C_STRING_H
#include "src/stdio/fprintf.h"
-#include "src/__support/File/file.h"
#include "src/__support/arg_list.h"
#include "src/stdio/printf_core/vfprintf_internal.h"
namespace __llvm_libc {
#ifndef LIBC_COPT_PRINTF_USE_SYSTEM_FILE
+#include "src/__support/File/file.h"
using FileT = __llvm_libc::File;
#else // defined(LIBC_COPT_PRINTF_USE_SYSTEM_FILE)
using FileT = ::FILE;
--- /dev/null
+//===-- Implementation of the file path generator for bazel ---------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibcTest.h"
+
+#include <stdlib.h>
+
+#include "src/__support/CPP/string.h"
+#include "src/__support/c_string.h"
+
+namespace __llvm_libc::testing {
+
+CString libc_make_test_file_path_func(const char *file_name) {
+ // This is the path to the folder bazel wants the test outputs written to.
+ const char *UNDECLARED_OUTPUTS_PATH = getenv("TEST_UNDECLARED_OUTPUTS_DIR");
+
+ return cpp::string(UNDECLARED_OUTPUTS_PATH) + file_name;
+}
+
+} // namespace __llvm_libc::testing
set(libc_test_srcs_common
Test.h
LibcTest.cpp
+ CmakeFilePath.cpp
LibcTest.h
TestLogger.cpp
TestLogger.h
target_compile_options(${lib} PRIVATE ${LIBC_HERMETIC_TEST_COMPILE_OPTIONS}
-fno-exceptions -fno-rtti)
add_dependencies(${lib}
+ libc.src.__support.c_string
libc.src.__support.CPP.string
libc.src.__support.CPP.string_view
libc.src.__support.CPP.type_traits
--- /dev/null
+//===-- Implementation of the file path generator for cmake ---------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibcTest.h"
+
+#include "src/__support/CPP/string.h"
+#include "src/__support/c_string.h"
+
+namespace __llvm_libc::testing {
+
+CString libc_make_test_file_path_func(const char *file_name) {
+ return cpp::string(file_name);
+}
+
+} // namespace __llvm_libc::testing
#ifndef LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H
#define LLVM_LIBC_UTILS_UNITTEST_LIBCTEST_H
-// This file can only include headers from src/__support/CPP/ or
-// utils/testutils. No other headers should be included.
+// This is defined as a simple macro in test.h so that it exists for platforms
+// that don't use our test infrastructure. It's defined as a proper function
+// below.
+#ifdef libc_make_test_file_path
+#undef libc_make_test_file_path
+#endif // libc_make_test_file_path
+
+// This is defined as a macro here to avoid namespace issues.
+#define libc_make_test_file_path(file_name) \
+ (__llvm_libc::testing::libc_make_test_file_path_func(file_name))
+
+// This file can only include headers from src/__support/ or test/UnitTest. No
+// other headers should be included.
#include "PlatformDefs.h"
#include "src/__support/CPP/string.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/type_traits.h"
+#include "src/__support/c_string.h"
#include "test/UnitTest/ExecuteFunction.h"
#include "test/UnitTest/TestLogger.h"
// Make TypeList visible in __llvm_libc::testing.
template <typename... Types> using TypeList = internal::TypeList<Types...>;
+CString libc_make_test_file_path_func(const char *file_name);
+
} // namespace testing
} // namespace __llvm_libc
#ifndef LLVM_LIBC_UTILS_UNITTEST_TEST_H
#define LLVM_LIBC_UTILS_UNITTEST_TEST_H
+// This macro takes a file name and returns a value implicitly castable to
+// a const char*. That const char* is the path to a file with the provided name
+// in a directory where the test is allowed to write. By default it writes
+// directly to the filename provided, but implementations are allowed to
+// redefine it as necessary.
+#define libc_make_test_file_path(file_name) (file_name)
+
#ifdef LIBC_COPT_TEST_USE_FUCHSIA
#include "FuchsiaTest.h"
#elif defined(LIBC_COPT_TEST_USE_PIGWEED)
} // namespace printf_test
TEST(LlvmLibcFPrintfTest, WriteToFile) {
- constexpr char FILENAME[] = "testdata/fprintf_output.test";
- ::FILE *file = printf_test::fopen(FILENAME, "w");
+ const char *FILENAME = "fprintf_output.test";
+ auto FILE_PATH = libc_make_test_file_path(FILENAME);
+
+ ::FILE *file = printf_test::fopen(FILE_PATH, "w");
ASSERT_FALSE(file == nullptr);
int written;
ASSERT_EQ(0, printf_test::fclose(file));
- file = printf_test::fopen(FILENAME, "r");
+ file = printf_test::fopen(FILE_PATH, "r");
ASSERT_FALSE(file == nullptr);
char data[50];
licenses(["notice"])
+PRINTF_COPTS = [
+ "LIBC_COPT_PRINTF_USE_SYSTEM_FILE",
+ "LIBC_COPT_PRINTF_DISABLE_INDEX_MODE",
+ "LIBC_COPT_PRINTF_DISABLE_WRITE_INT",
+]
+
# A flag to pick which `mpfr` to use for math tests.
# Usage: `--@llvm-project//libc:mpfr=<disable|external|system>`.
# Flag documentation: https://bazel.build/extending/config
)
libc_support_library(
+ name = "__support_cpp_expected",
+ hdrs = ["src/__support/CPP/expected.h"],
+ deps = [
+ ":libc_root",
+ ],
+)
+
+libc_support_library(
name = "__support_cpp_functional",
hdrs = ["src/__support/CPP/functional.h"],
deps = [
)
libc_support_library(
+ name = "__support_cpp_new",
+ srcs = ["src/__support/CPP/new.cpp"],
+ hdrs = ["src/__support/CPP/new.h"],
+ deps = [
+ ":__support_common",
+ ":libc_root",
+ ],
+)
+
+libc_support_library(
name = "__support_cpp_optional",
hdrs = ["src/__support/CPP/optional.h"],
deps = [":libc_root"],
)
libc_support_library(
+ name = "__support_c_string",
+ hdrs = ["src/__support/c_string.h"],
+ deps = [
+ ":__support_cpp_string",
+ ":libc_root",
+ ],
+)
+
+libc_support_library(
+ name = "__support_error_or",
+ hdrs = ["src/__support/error_or.h"],
+ deps = [
+ ":__support_common",
+ ":__support_cpp_expected",
+ ":libc_root",
+ ],
+)
+
+libc_support_library(
name = "__support_float_to_string",
hdrs = [
"src/__support/float_to_string.h",
)
libc_support_library(
+ name = "__support_file_file",
+ srcs = ["src/__support/File/file.cpp"],
+ hdrs = ["src/__support/File/file.h"],
+ deps = [
+ ":__support_cpp_new",
+ ":__support_cpp_span",
+ ":__support_error_or",
+ ":__support_threads_mutex",
+ ":errno",
+ ":libc_root",
+ ],
+)
+
+libc_support_library(
name = "__support_named_pair",
hdrs = ["src/__support/named_pair.h"],
deps = [":libc_root"],
],
)
+libc_support_library(
+ name = "__support_threads_mutex",
+ hdrs = [
+ "src/__support/threads/mutex.h",
+ "src/__support/threads/mutex_common.h",
+ ],
+ textual_hdrs = [
+ "src/__support/threads/linux/mutex.h",
+ "src/__support/threads/linux/futex_word.h",
+ ],
+ deps = [
+ ":__support_cpp_atomic",
+ ":__support_osutil_syscall",
+ ":libc_root",
+ ],
+)
+
############################### errno targets ################################
libc_function(
libc_support_library(
name = "printf_core_structs",
hdrs = ["src/stdio/printf_core/core_structs.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_cpp_string_view",
":__support_fputil_fp_bits",
libc_support_library(
name = "printf_config",
hdrs = ["src/stdio/printf_core/printf_config.h"],
+ defines = PRINTF_COPTS,
deps = [
":libc_root",
],
name = "printf_parser",
srcs = ["src/stdio/printf_core/parser.cpp"],
hdrs = ["src/stdio/printf_core/parser.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":__support_common",
name = "printf_mock_parser",
srcs = ["src/stdio/printf_core/parser.cpp"],
hdrs = ["src/stdio/printf_core/parser.h"],
- copts = ["-DLIBC_COPT_MOCK_ARG_LIST"],
+ defines = PRINTF_COPTS + ["LIBC_COPT_MOCK_ARG_LIST"],
deps = [
":__support_arg_list",
":__support_common",
name = "printf_string_writer",
srcs = ["src/stdio/printf_core/string_writer.cpp"],
hdrs = ["src/stdio/printf_core/string_writer.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_cpp_string_view",
":libc_root",
)
libc_support_library(
+ name = "printf_file_writer",
+ hdrs = ["src/stdio/printf_core/file_writer.h"],
+ defines = PRINTF_COPTS,
+ deps = [
+ ":__support_cpp_string_view",
+ ":__support_file_file",
+ ":libc_root",
+ ":printf_core_structs",
+ ],
+)
+
+libc_support_library(
name = "printf_writer",
srcs = ["src/stdio/printf_core/writer.cpp"],
hdrs = ["src/stdio/printf_core/writer.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_cpp_string_view",
":libc_root",
"src/stdio/printf_core/string_converter.h",
"src/stdio/printf_core/write_int_converter.h",
],
+ defines = PRINTF_COPTS,
deps = [
":__support_common",
":__support_cpp_limits",
name = "printf_main",
srcs = ["src/stdio/printf_core/printf_main.cpp"],
hdrs = ["src/stdio/printf_core/printf_main.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":libc_root",
name = "sprintf",
srcs = ["src/stdio/sprintf.cpp"],
hdrs = ["src/stdio/sprintf.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":errno",
name = "snprintf",
srcs = ["src/stdio/snprintf.cpp"],
hdrs = ["src/stdio/snprintf.h"],
+ defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":errno",
":printf_writer",
],
)
+
+libc_support_library(
+ name = "vfprintf_internal",
+ hdrs = ["src/stdio/printf_core/vfprintf_internal.h"],
+ defines = PRINTF_COPTS,
+ deps = [
+ ":__support_arg_list",
+ ":__support_file_file",
+ ":__support_macros_attributes",
+ ":printf_file_writer",
+ ":printf_main",
+ ":printf_writer",
+ ],
+)
+
+libc_function(
+ name = "printf",
+ srcs = ["src/stdio/printf.cpp"],
+ hdrs = ["src/stdio/printf.h"],
+ defines = PRINTF_COPTS,
+ deps = [
+ ":__support_arg_list",
+ ":errno",
+ ":vfprintf_internal",
+ ],
+)
+
+libc_function(
+ name = "fprintf",
+ srcs = ["src/stdio/fprintf.cpp"],
+ hdrs = ["src/stdio/fprintf.h"],
+ defines = PRINTF_COPTS,
+ deps = [
+ ":__support_arg_list",
+ ":errno",
+ ":vfprintf_internal",
+ ],
+)
# We want all libc sources to be compiled with "hidden" visibility.
# The public symbols will be given "default" visibility explicitly.
# See src/__support/common.h for more information.
- copts.append("-fvisibility=hidden")
+ copts = copts + ["-fvisibility=hidden"]
native.cc_library(
name = name,
copts = copts,
**kwargs: Other attributes relevant for a cc_library. For example, deps.
"""
deps = deps or []
- deps.append(LIBC_ROOT_TARGET)
+ # We use the explicit equals pattern here because append and += mutate the
+ # original list, where this creates a new list and stores it in deps.
+ deps = deps + [LIBC_ROOT_TARGET]
copts = copts or []
- copts.append("-O3")
- copts.append("-fno-builtin")
- copts.append("-fno-lax-vector-conversions")
+ copts = copts + ["-O3", "-fno-builtin", "-fno-lax-vector-conversions"]
# We compile the code twice, the first target is suffixed with ".__internal__" and contains the
# C++ functions in the "__llvm_libc" namespace. This allows us to test the function in the
func_attrs = ["__attribute__((visibility(\"default\")))"]
if weak:
- func_attrs.append("__attribute__((weak))")
+ func_attrs = func_attrs + ["__attribute__((weak))"]
local_defines = local_defines or ["LIBC_COPT_PUBLIC_PACKAGING"]
- local_defines.append("LLVM_LIBC_FUNCTION_ATTR='%s'" % " ".join(func_attrs))
+ local_defines = local_defines + ["LLVM_LIBC_FUNCTION_ATTR='%s'" % " ".join(func_attrs)]
_libc_library(
name = name,
srcs = srcs,
cc_library(
name = "LibcUnitTest",
srcs = [
+ "BazelFilePath.cpp",
"ExecuteFunctionUnix.cpp",
"LibcTest.cpp",
"LibcTestMain.cpp",
],
deps = [
":test_logger",
+ "//libc:__support_c_string",
"//libc:__support_cpp_bit",
"//libc:__support_cpp_bitset",
"//libc:__support_cpp_span",
libc_function_deps = [
],
deps = [
- "//libc:printf_string_writer",
- "//libc:printf_writer",
- "//libc:printf_core_structs",
- "//libc:__support_cpp_string_view",
- "//libc:__support_arg_list",
+ "//libc:__support_arg_list",
+ "//libc:__support_cpp_string_view",
+ "//libc:printf_core_structs",
+ "//libc:printf_string_writer",
+ "//libc:printf_writer",
],
)
libc_function_deps = [
],
deps = [
- "//libc:printf_converter",
- "//libc:printf_string_writer",
- "//libc:printf_writer",
- "//libc:printf_core_structs",
- "//libc:__support_cpp_string_view",
- "//libc:__support_arg_list",
+ "//libc:__support_arg_list",
+ "//libc:__support_cpp_string_view",
+ "//libc:printf_converter",
+ "//libc:printf_core_structs",
+ "//libc:printf_string_writer",
+ "//libc:printf_writer",
],
)
"//libc:snprintf",
],
)
+
+libc_test(
+ name = "printf_test",
+ srcs = ["printf_test.cpp"],
+ libc_function_deps = [
+ "//libc:printf",
+ ],
+)
+
+libc_test(
+ name = "fprintf_test",
+ srcs = ["fprintf_test.cpp"],
+ libc_function_deps = [
+ "//libc:fprintf",
+ ],
+)