[libc][bazel] add file printf targets and support

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
This commit is contained in:
Michael Jones
2023-03-27 15:14:17 -07:00
parent bbc7b30fbf
commit d94fe97280
13 changed files with 291 additions and 25 deletions

View File

@@ -45,6 +45,15 @@ add_header_library(
libc.src.__support.CPP.expected
)
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

View File

@@ -0,0 +1,36 @@
//===-- 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

View File

@@ -8,7 +8,6 @@
#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"
@@ -18,6 +17,7 @@
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;

View File

@@ -0,0 +1,25 @@
//===-- 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

View File

@@ -1,6 +1,7 @@
set(libc_test_srcs_common
Test.h
LibcTest.cpp
CmakeFilePath.cpp
LibcTest.h
TestLogger.cpp
TestLogger.h
@@ -29,6 +30,7 @@ foreach(lib LibcUnitTest LibcHermeticTest)
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

View File

@@ -0,0 +1,20 @@
//===-- 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

View File

@@ -9,14 +9,26 @@
#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"
@@ -259,6 +271,8 @@ template <typename... Types> struct TypeList {
// 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

View File

@@ -9,6 +9,13 @@
#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)

View File

@@ -34,8 +34,10 @@ using ::fread;
} // 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;
@@ -55,7 +57,7 @@ TEST(LlvmLibcFPrintfTest, WriteToFile) {
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];

View File

@@ -20,6 +20,12 @@ package(
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
@@ -153,6 +159,14 @@ libc_support_library(
],
)
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"],
@@ -170,6 +184,16 @@ libc_support_library(
deps = [":libc_root"],
)
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"],
@@ -244,6 +268,25 @@ libc_support_library(
],
)
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 = [
@@ -398,6 +441,20 @@ libc_support_library(
],
)
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"],
@@ -701,6 +758,23 @@ libc_support_library(
],
)
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(
@@ -2080,6 +2154,7 @@ 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",
@@ -2090,6 +2165,7 @@ libc_support_library(
libc_support_library(
name = "printf_config",
hdrs = ["src/stdio/printf_core/printf_config.h"],
defines = PRINTF_COPTS,
deps = [
":libc_root",
],
@@ -2099,6 +2175,7 @@ libc_support_library(
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",
@@ -2120,7 +2197,7 @@ libc_support_library(
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",
@@ -2141,6 +2218,7 @@ libc_support_library(
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",
@@ -2149,10 +2227,23 @@ libc_support_library(
],
)
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",
@@ -2175,6 +2266,7 @@ libc_support_library(
"src/stdio/printf_core/string_converter.h",
"src/stdio/printf_core/write_int_converter.h",
],
defines = PRINTF_COPTS,
deps = [
":__support_common",
":__support_cpp_limits",
@@ -2197,6 +2289,7 @@ libc_support_library(
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",
@@ -2211,6 +2304,7 @@ libc_function(
name = "sprintf",
srcs = ["src/stdio/sprintf.cpp"],
hdrs = ["src/stdio/sprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":errno",
@@ -2224,6 +2318,7 @@ libc_function(
name = "snprintf",
srcs = ["src/stdio/snprintf.cpp"],
hdrs = ["src/stdio/snprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":errno",
@@ -2232,3 +2327,41 @@ libc_function(
":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",
],
)

View File

@@ -23,7 +23,7 @@ def _libc_library(name, copts = None, **kwargs):
# 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,
@@ -65,11 +65,11 @@ def libc_function(
**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
@@ -87,9 +87,9 @@ def libc_function(
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,

View File

@@ -23,6 +23,7 @@ cc_library(
cc_library(
name = "LibcUnitTest",
srcs = [
"BazelFilePath.cpp",
"ExecuteFunctionUnix.cpp",
"LibcTest.cpp",
"LibcTestMain.cpp",
@@ -35,6 +36,7 @@ cc_library(
],
deps = [
":test_logger",
"//libc:__support_c_string",
"//libc:__support_cpp_bit",
"//libc:__support_cpp_bitset",
"//libc:__support_cpp_span",

View File

@@ -31,11 +31,11 @@ libc_test(
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",
],
)
@@ -45,12 +45,12 @@ libc_test(
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",
],
)
@@ -74,3 +74,19 @@ libc_test(
"//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",
],
)