# Copyright 2023 The Pigweed Authors
#
# Licensed 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
#
#     https://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("//build_overrides/pigweed.gni")

import("$dir_pw_build/target_types.gni")
import("$dir_pw_toolchain/generate_toolchain.gni")
import("$dir_pw_unit_test/test.gni")
import("$pw_external_llvm_libc/llvm_libc.gni")

config("default_config") {
  include_dirs = [ "public" ]
}

pw_test_group("tests") {
  tests = [
    ":llvm_libc_tests",
    ":logf_test",
    ":memset_test",
  ]
}

pw_test("memset_test") {
  sources = [ "memset_test.cc" ]
  deps = [ "$dir_pw_containers" ]
}

pw_test("logf_test") {
  sources = [ "logf_test.cc" ]
}

# Clang has __attribute__(("no-builtin")), but gcc doesn't support it so we
# need this flag instead.
config("no-builtin") {
  cflags = [ "-fno-builtin" ]
}

# Downstream projects sometimes build with -Wshadow, which on gcc also warns
# about constructor arguments shadowing struct members. This is too pedantic
# and not reasonable to change upstream llvm-libc.
config("no-shadow") {
  cflags = [ "-Wno-shadow" ]
}

# If dir_pw_third_party_llvm_libc is defined, use that directory to create a
# pw_libc.a from llvm-libc. Otherwise, we create an empty pw_libc.a.
if (dir_pw_third_party_llvm_libc != "") {
  pw_libc_source_set("stdlib") {
    functions = [
      "abs",
      "rand",
      "srand",
    ]
    additional_srcs = [
      "baremetal/abort.cpp",
      "rand_util.cpp",
    ]

    # srand and rand are both tested in rand_test.cpp.
    no_test_functions = [ "srand" ]
  }

  pw_libc_source_set("string") {
    defines = [ "LIBC_COPT_MEMCPY_USE_EMBEDDED_TINY" ]
    functions = [
      "strcmp",
      "strcpy",
      "strstr",
      "strncpy",
      "strnlen",
      "memcpy",
      "memset",
      "memmove",
    ]

    # memmove tests use gtest matchers which pw_unit_test doesn't support.
    no_test_functions = [ "memmove" ]

    configs = [
      ":no-builtin",
      ":no-shadow",
    ]
  }

  pw_libc_source_set("ctype") {
    functions = [ "isprint" ]
  }

  pw_libc_source_set("time") {
    functions = [ "gmtime" ]
    additional_srcs = [ "time_utils.cpp" ]

    # gmtime requires gtest matchers which pw_unit_test doesn't support.
    # Moreover, the matches in llvm-libc don't have the same internal API that
    # gtest does, so it isn't possible to enable this tests when using gtest
    # either.
    no_test_functions = [ "gmtime" ]
  }

  pw_libc_source_set("math") {
    non_cpu_dir = "generic"

    functions = [
      "modff",
      "roundf",
    ]

    # Math tests require the MPFR library, which is not available.
    no_test_functions = functions
  }

  pw_libc_source_set("stdio") {
    functions = [
      "snprintf",
      "vsnprintf",
    ]

    additional_srcs = [
      "printf_core/printf_main.cpp",
      "printf_core/writer.cpp",
      "printf_core/converter.cpp",
    ]

    # If we happen to be using pw_libc for host, let's keep all the normal features.
    if (current_os != host_os) {
      defines = [
        "LIBC_COPT_PRINTF_DISABLE_FLOAT",
        "LIBC_COPT_PRINTF_DISABLE_WRITE_INT",
        "LIBC_COPT_PRINTF_DISABLE_INDEX_MODE",
      ]
    }

    # This config includes -Wshadow. On gcc, this warns even for constructor
    # arguments which shadow members. This is too pedantic and shouldn't be
    # changed upstream.
    remove_configs = [ "$dir_pw_build:extra_strict_warnings" ]
    configs = [ ":no-shadow" ]
  }

  pw_libc_source_set("stdfix") {
    functions = [
      "expk",
      "roundlk",
      "sqrtulr",
      "sqrtur",
      "uksqrtui",
    ]
    defines = [ "LIBC_FAST_MATH=1" ]
  }

  pw_static_library("pw_libc") {
    complete_static_lib = true
    add_global_link_deps = false
    deps = [
      ":ctype",
      ":math",
      ":stdio",
      ":stdlib",
      ":string",
      ":time",
    ]
  }

  pw_test_group("llvm_libc_tests") {
    tests = [
      ":ctype_tests",
      ":math_tests",
      ":stdio_tests",
      ":stdlib_tests",
      ":string_tests",
      ":time_tests",
    ]
  }

  pw_static_library("pw_libc_stdfix") {
    complete_static_lib = true
    add_global_link_deps = false
    deps = [
      ":stdfix",
      ":stdio",
    ]
  }
} else {
  pw_static_library("pw_libc") {
    add_global_link_deps = false
  }

  pw_static_library("pw_libc_stdfix") {
    add_global_link_deps = false
  }

  pw_test_group("llvm_libc_tests") {
  }
}

pw_static_library("noop_io") {
  sources = [ "noop_io.cc" ]
}

pw_static_library("errno") {
  sources = [ "errno.cc" ]
}
