# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//common-mk/deps.gni")
import("//common-mk/pkg_config.gni")
import("//common-mk/proto_library.gni")

group("all") {
  deps = [
    ":libbrillo",
    ":libbrillo-glib",
    ":libbrillo-test",
    ":libinstallattributes",
    ":libpolicy",
  ]
  if (use.test) {
    deps += [
      ":libbrillo_tests",
      ":libinstallattributes_tests",
      ":libpolicy_tests",
    ]
  }
  if (use.fuzzer) {
    deps += [
      ":libbrillo_data_encoding_fuzzer",
      ":libbrillo_dbus_data_serialization_fuzzer",
      ":libbrillo_http_form_data_fuzzer",
    ]
  }
}

default_pkg_deps = [ "libchrome-${libbase_ver}" ]
pkg_config("target_defaults_pkg_deps") {
  pkg_deps = default_pkg_deps
}

config("target_defaults") {
  configs = [ ":target_defaults_pkg_deps" ]
  include_dirs = [ "../libbrillo" ]
  defines = [
    "USE_DBUS=${use.dbus}",
    "USE_RTTI_FOR_TYPE_TAGS",
  ]
}

config("libbrillo_configs") {
  include_dirs = [ "../libbrillo" ]
}

# Properties of shared libraries which libbrillo consists of.
# Stored to variables once before actually declaring the targets, so that
# another target can collect information for making the .pc and .so files.
libbrillo_sublibs = [
  {
    # |library_name| is library file name without "lib" prefix. This is needed
    # for composing -l*** flags in libbrillo-${libbasever}.so.
    # (Current version of GN deployed to ChromeOS doesn't have string_replace.)
    library_name = "brillo-core"
    if (use.dbus) {
      all_dependent_pkg_deps = [ "dbus-1" ]
    }
    libs = [ "modp_b64" ]
    sources = [
      "brillo/asynchronous_signal_handler.cc",
      "brillo/backoff_entry.cc",
      "brillo/daemons/daemon.cc",
      "brillo/data_encoding.cc",
      "brillo/errors/error.cc",
      "brillo/errors/error_codes.cc",
      "brillo/file_utils.cc",
      "brillo/files/file_util.cc",
      "brillo/files/safe_fd.cc",
      "brillo/flag_helper.cc",
      "brillo/key_value_store.cc",
      "brillo/message_loops/base_message_loop.cc",
      "brillo/message_loops/message_loop.cc",
      "brillo/message_loops/message_loop_utils.cc",
      "brillo/mime_utils.cc",
      "brillo/osrelease_reader.cc",
      "brillo/process.cc",
      "brillo/process_information.cc",
      "brillo/process_reaper.cc",
      "brillo/scoped_umask.cc",
      "brillo/secure_blob.cc",
      "brillo/strings/string_utils.cc",
      "brillo/syslog_logging.cc",
      "brillo/timezone/tzif_parser.cc",
      "brillo/type_name_undecorate.cc",
      "brillo/url_utils.cc",
      "brillo/userdb_utils.cc",
      "brillo/value_conversion.cc",
    ]
    if (use.dbus) {
      sources += [
        "brillo/any.cc",
        "brillo/daemons/dbus_daemon.cc",
        "brillo/dbus/async_event_sequencer.cc",
        "brillo/dbus/data_serialization.cc",
        "brillo/dbus/dbus_connection.cc",
        "brillo/dbus/dbus_method_invoker.cc",
        "brillo/dbus/dbus_method_response.cc",
        "brillo/dbus/dbus_object.cc",
        "brillo/dbus/dbus_service_watcher.cc",
        "brillo/dbus/dbus_signal.cc",
        "brillo/dbus/exported_object_manager.cc",
        "brillo/dbus/exported_property_set.cc",
        "brillo/dbus/introspectable_helper.cc",
        "brillo/dbus/utils.cc",
      ]
    }
  },

  {
    library_name = "brillo-blockdeviceutils"
    deps = [ ":libbrillo-core" ]
    sources = [ "brillo/blkdev_utils/loop_device.cc" ]
    if (use.device_mapper) {
      pkg_deps = [ "devmapper" ]
      sources += [
        "brillo/blkdev_utils/device_mapper.cc",
        "brillo/blkdev_utils/device_mapper_task.cc",
      ]
    }
  },

  {
    library_name = "brillo-http"
    deps = [
      ":libbrillo-core",
      ":libbrillo-streams",
    ]
    all_dependent_pkg_deps = [ "libcurl" ]
    sources = [
      "brillo/http/curl_api.cc",
      "brillo/http/http_connection_curl.cc",
      "brillo/http/http_form_data.cc",
      "brillo/http/http_request.cc",
      "brillo/http/http_transport.cc",
      "brillo/http/http_transport_curl.cc",
      "brillo/http/http_utils.cc",
    ]
    if (use.dbus) {
      sources += [ "brillo/http/http_proxy.cc" ]
    }
  },

  {
    library_name = "brillo-streams"
    deps = [ ":libbrillo-core" ]
    all_dependent_pkg_deps = [ "openssl" ]
    sources = [
      "brillo/streams/file_stream.cc",
      "brillo/streams/input_stream_set.cc",
      "brillo/streams/memory_containers.cc",
      "brillo/streams/memory_stream.cc",
      "brillo/streams/openssl_stream_bio.cc",
      "brillo/streams/stream.cc",
      "brillo/streams/stream_errors.cc",
      "brillo/streams/stream_utils.cc",
      "brillo/streams/tls_stream.cc",
    ]
  },

  {
    library_name = "brillo-cryptohome"
    all_dependent_pkg_deps = [ "openssl" ]
    sources = [ "brillo/cryptohome.cc" ]
  },

  {
    library_name = "brillo-namespaces"
    deps = [ ":libbrillo-core" ]
    sources = [
      "brillo/namespaces/mount_namespace.cc",
      "brillo/namespaces/platform.cc",
      "brillo/scoped_mount_namespace.cc",
    ]
  },

  {
    library_name = "brillo-minijail"
    all_dependent_pkg_deps = [ "libminijail" ]
    sources = [ "brillo/minijail/minijail.cc" ]
  },

  {
    library_name = "brillo-protobuf"
    all_dependent_pkg_deps = [ "protobuf" ]
    sources = [ "brillo/proto_file_io.cc" ]
  },
]

if (use.udev) {
  libbrillo_sublibs += [
    {
      library_name = "brillo-udev"
      all_dependent_pkg_deps = [ "libudev" ]
      sources = [
        "brillo/udev/udev.cc",
        "brillo/udev/udev_device.cc",
        "brillo/udev/udev_enumerate.cc",
        "brillo/udev/udev_list_entry.cc",
        "brillo/udev/udev_monitor.cc",
      ]
    },
  ]
}

# Generate shared libraries.
foreach(attr, libbrillo_sublibs) {
  shared_library("lib" + attr.library_name) {
    sources = attr.sources
    if (defined(attr.deps)) {
      deps = attr.deps
    }
    if (defined(attr.libs)) {
      libs = attr.libs
    }
    if (defined(attr.pkg_deps)) {
      pkg_deps = attr.pkg_deps
    }
    if (defined(attr.public_pkg_deps)) {
      public_pkg_deps = attr.public_pkg_deps
    }
    if (defined(attr.all_dependent_pkg_deps)) {
      all_dependent_pkg_deps = attr.all_dependent_pkg_deps
    }
    if (defined(attr.cflags)) {
      cflags = attr.cflags
    }
    if (defined(attr.configs)) {
      configs += attr.configs
    }
    configs += [ ":target_defaults" ]
  }
}

generate_pkg_config("libbrillo-${libbase_ver}_pc") {
  name = "libbrillo"
  output_name = "libbrillo-${libbase_ver}"
  description = "brillo base library"
  version = libbase_ver
  requires_private = default_pkg_deps
  foreach(sublib, libbrillo_sublibs) {
    if (defined(sublib.pkg_deps)) {
      requires_private += sublib.pkg_deps
    }
    if (defined(sublib.public_pkg_deps)) {
      requires_private += sublib.public_pkg_deps
    }
    if (defined(sublib.all_dependent_pkg_deps)) {
      requires_private += sublib.all_dependent_pkg_deps
    }
  }
  defines = [ "USE_RTTI_FOR_TYPE_TAGS" ]
  libs = [ "-lbrillo" ]
}

generate_pkg_config("libbrillo_pc") {
  name = "libbrillo"
  output_name = "libbrillo"
  description = "brillo base library"
  version = libbase_ver
  requires_private = default_pkg_deps
  foreach(sublib, libbrillo_sublibs) {
    if (defined(sublib.pkg_deps)) {
      requires_private += sublib.pkg_deps
    }
    if (defined(sublib.public_pkg_deps)) {
      requires_private += sublib.public_pkg_deps
    }
    if (defined(sublib.all_dependent_pkg_deps)) {
      requires_private += sublib.all_dependent_pkg_deps
    }
  }
  defines = [ "USE_RTTI_FOR_TYPE_TAGS" ]
  libs = [ "-lbrillo" ]
}

action("libbrillo") {
  deps = [
    ":libbrillo-${libbase_ver}_pc",
    ":libbrillo_pc",
  ]
  foreach(sublib, libbrillo_sublibs) {
    deps += [ ":lib" + sublib.library_name ]
  }
  script = "//common-mk/write_args.py"
  outputs = [ "${root_out_dir}/lib/libbrillo.so" ]
  args = [ "--output" ] + outputs + [ "--" ] + [
           "GROUP",
           "(",
           "AS_NEEDED",
           "(",
         ]
  foreach(sublib, libbrillo_sublibs) {
    args += [ "-l" + sublib.library_name ]
  }
  args += [
    ")",
    ")",
  ]
}

libbrillo_test_deps = [ "libbrillo-http" ]

generate_pkg_config("libbrillo-test-${libbase_ver}_pc") {
  name = "libbrillo-test"
  output_name = "libbrillo-test-${libbase_ver}"
  description = "brillo test library"
  version = libbase_ver

  # Because libbrillo-test is static, we have to depend directly on everything.
  requires = [ "libbrillo" ] + default_pkg_deps
  foreach(name, libbrillo_test_deps) {
    foreach(t, libbrillo_sublibs) {
      if ("lib" + t.library_name == name) {
        if (defined(t.pkg_deps)) {
          requires += t.pkg_deps
        }
        if (defined(t.public_pkg_deps)) {
          requires += t.public_pkg_deps
        }
        if (defined(t.all_dependent_pkg_deps)) {
          requires += t.all_dependent_pkg_deps
        }
      }
    }
  }
  libs = [ "-lbrillo-test" ]
}

generate_pkg_config("libbrillo-test_pc") {
  name = "libbrillo-test"
  output_name = "libbrillo-test"
  description = "brillo test library"
  version = libbase_ver

  # Because libbrillo-test is static, we have to depend directly on everything.
  requires = [ "libbrillo" ] + default_pkg_deps
  foreach(name, libbrillo_test_deps) {
    foreach(t, libbrillo_sublibs) {
      if ("lib" + t.library_name == name) {
        if (defined(t.pkg_deps)) {
          requires += t.pkg_deps
        }
        if (defined(t.public_pkg_deps)) {
          requires += t.public_pkg_deps
        }
        if (defined(t.all_dependent_pkg_deps)) {
          requires += t.all_dependent_pkg_deps
        }
      }
    }
  }
  libs = [ "-lbrillo-test" ]
}

static_library("libbrillo-test") {
  configs -= [ "//common-mk:use_thin_archive" ]
  configs += [
    "//common-mk:nouse_thin_archive",
    ":target_defaults",
  ]
  deps = [
    ":libbrillo-http",
    ":libbrillo-test-${libbase_ver}_pc",
    ":libbrillo-test_pc",
  ]
  foreach(name, libbrillo_test_deps) {
    deps += [ ":" + name ]
  }
  sources = [
    "brillo/blkdev_utils/loop_device_fake.cc",
    "brillo/http/http_connection_fake.cc",
    "brillo/http/http_transport_fake.cc",
    "brillo/message_loops/fake_message_loop.cc",
    "brillo/streams/fake_stream.cc",
    "brillo/unittest_utils.cc",
  ]
  if (use.device_mapper) {
    sources += [ "brillo/blkdev_utils/device_mapper_fake.cc" ]
  }
}

shared_library("libinstallattributes") {
  configs += [ ":target_defaults" ]
  deps = [
    ":libinstallattributes-includes",
    "../common-mk/external_dependencies:install_attributes-proto",
  ]
  all_dependent_pkg_deps = [ "protobuf-lite" ]
  sources = [ "install_attributes/libinstallattributes.cc" ]
}

shared_library("libpolicy") {
  configs += [ ":target_defaults" ]
  deps = [
    ":libinstallattributes",
    ":libpolicy-includes",
    "../common-mk/external_dependencies:policy-protos",
  ]
  all_dependent_pkg_deps = [
    "openssl",
    "protobuf-lite",
  ]
  ldflags = [ "-Wl,--version-script,${platform2_root}/libbrillo/libpolicy.ver" ]
  sources = [
    "policy/device_policy.cc",
    "policy/device_policy_impl.cc",
    "policy/libpolicy.cc",
    "policy/policy_util.cc",
    "policy/resilient_policy_util.cc",
  ]
}

libbrillo_glib_pkg_deps = [
  "glib-2.0",
  "gobject-2.0",
]
if (use.dbus) {
  libbrillo_glib_pkg_deps += [
    "dbus-1",
    "dbus-glib-1",
  ]
}

generate_pkg_config("libbrillo-glib-${libbase_ver}_pc") {
  name = "libbrillo-glib"
  output_name = "libbrillo-glib-${libbase_ver}"
  description = "brillo glib wrapper library"
  version = libbase_ver
  requires_private = libbrillo_glib_pkg_deps
  libs = [ "-lbrillo-glib" ]
}

generate_pkg_config("libbrillo-glib_pc") {
  name = "libbrillo-glib"
  output_name = "libbrillo-glib"
  description = "brillo glib wrapper library"
  version = libbase_ver
  requires_private = libbrillo_glib_pkg_deps
  libs = [ "-lbrillo-glib" ]
}

shared_library("libbrillo-glib") {
  configs += [ ":target_defaults" ]
  deps = [
    ":libbrillo",
    ":libbrillo-glib-${libbase_ver}_pc",
    ":libbrillo-glib_pc",
  ]
  all_dependent_pkg_deps = libbrillo_glib_pkg_deps
  if (use.dbus) {
    sources = [
      "brillo/glib/abstract_dbus_service.cc",
      "brillo/glib/dbus.cc",
    ]
  }
  cflags = [
    # glib uses the deprecated "register" attribute in some header files.
    "-Wno-deprecated-register",
  ]
}

if (use.test) {
  static_library("libbrillo_static") {
    configs += [ ":target_defaults" ]
    deps = [
      ":libbrillo-${libbase_ver}_pc",
      ":libbrillo_pc",
      ":libinstallattributes",
      ":libpolicy",
    ]
    foreach(sublib, libbrillo_sublibs) {
      deps += [ ":lib" + sublib.library_name ]
    }
    public_configs = [ ":libbrillo_configs" ]
  }
  proto_library("libbrillo_tests_proto") {
    proto_in_dir = "brillo/dbus"
    proto_out_dir = "include/brillo/dbus"
    sources = [ "${proto_in_dir}/test.proto" ]
  }
  executable("libbrillo_tests") {
    configs += [
      "//common-mk:test",
      ":target_defaults",
    ]
    deps = [
      ":libbrillo-glib",
      ":libbrillo-test",
      ":libbrillo_static",
      ":libbrillo_tests_proto",
    ]
    pkg_deps = [ "libchrome-test-${libbase_ver}" ]
    cflags = [ "-Wno-format-zero-length" ]

    if (is_debug) {
      cflags += [
        "-fprofile-arcs",
        "-ftest-coverage",
        "-fno-inline",
      ]
      libs = [ "gcov" ]
    }
    sources = [
      "brillo/asynchronous_signal_handler_test.cc",
      "brillo/backoff_entry_test.cc",
      "brillo/blkdev_utils/loop_device_test.cc",
      "brillo/data_encoding_test.cc",
      "brillo/enum_flags_test.cc",
      "brillo/errors/error_codes_test.cc",
      "brillo/errors/error_test.cc",
      "brillo/file_utils_test.cc",
      "brillo/files/file_util_test.cc",
      "brillo/files/safe_fd_test.cc",
      "brillo/flag_helper_test.cc",
      "brillo/glib/object_test.cc",
      "brillo/http/http_connection_curl_test.cc",
      "brillo/http/http_form_data_test.cc",
      "brillo/http/http_request_test.cc",
      "brillo/http/http_transport_curl_test.cc",
      "brillo/http/http_utils_test.cc",
      "brillo/key_value_store_test.cc",
      "brillo/map_utils_test.cc",
      "brillo/message_loops/base_message_loop_test.cc",
      "brillo/message_loops/fake_message_loop_test.cc",
      "brillo/message_loops/message_loop_test.cc",
      "brillo/mime_utils_test.cc",
      "brillo/namespaces/mount_namespace_test.cc",
      "brillo/osrelease_reader_test.cc",
      "brillo/process_reaper_test.cc",
      "brillo/process_test.cc",
      "brillo/scoped_umask_test.cc",
      "brillo/secure_blob_test.cc",
      "brillo/streams/fake_stream_test.cc",
      "brillo/streams/file_stream_test.cc",
      "brillo/streams/input_stream_set_test.cc",
      "brillo/streams/memory_containers_test.cc",
      "brillo/streams/memory_stream_test.cc",
      "brillo/streams/openssl_stream_bio_test.cc",
      "brillo/streams/stream_test.cc",
      "brillo/streams/stream_utils_test.cc",
      "brillo/strings/string_utils_test.cc",
      "brillo/timezone/tzif_parser_test.cc",
      "brillo/unittest_utils.cc",
      "brillo/url_utils_test.cc",
      "brillo/value_conversion_test.cc",
      "testrunner.cc",
    ]
    if (use.dbus) {
      sources += [
        "brillo/any_internal_impl_test.cc",
        "brillo/any_test.cc",
        "brillo/dbus/async_event_sequencer_test.cc",
        "brillo/dbus/data_serialization_test.cc",
        "brillo/dbus/dbus_method_invoker_test.cc",
        "brillo/dbus/dbus_object_test.cc",
        "brillo/dbus/dbus_param_reader_test.cc",
        "brillo/dbus/dbus_param_writer_test.cc",
        "brillo/dbus/dbus_signal_handler_test.cc",
        "brillo/dbus/exported_object_manager_test.cc",
        "brillo/dbus/exported_property_set_test.cc",
        "brillo/http/http_proxy_test.cc",
        "brillo/type_name_undecorate_test.cc",
        "brillo/variant_dictionary_test.cc",
      ]
    }
    if (use.device_mapper) {
      sources += [ "brillo/blkdev_utils/device_mapper_test.cc" ]
    }
  }

  executable("libinstallattributes_tests") {
    configs += [
      "//common-mk:test",
      ":target_defaults",
    ]
    deps = [
      ":libinstallattributes",
      "../common-mk/external_dependencies:install_attributes-proto",
      "../common-mk/testrunner:testrunner",
    ]
    sources = [ "install_attributes/tests/libinstallattributes_test.cc" ]
  }

  executable("libpolicy_tests") {
    configs += [
      "//common-mk:test",
      ":target_defaults",
    ]
    deps = [
      ":libinstallattributes",
      ":libpolicy",
      "../common-mk/external_dependencies:install_attributes-proto",
      "../common-mk/external_dependencies:policy-protos",
      "../common-mk/testrunner:testrunner",
    ]
    sources = [
      "install_attributes/mock_install_attributes_reader.cc",
      "policy/tests/device_policy_impl_test.cc",
      "policy/tests/libpolicy_test.cc",
      "policy/tests/policy_util_test.cc",
      "policy/tests/resilient_policy_util_test.cc",
    ]
  }
}

if (use.fuzzer) {
  executable("libbrillo_data_encoding_fuzzer") {
    sources = [ "brillo/data_encoding_fuzzer.cc" ]

    configs += [ "//common-mk/common_fuzzer:common_fuzzer" ]

    pkg_deps = [ "libchrome-${libbase_ver}" ]

    include_dirs = [ "../libbrillo" ]

    deps = [ ":libbrillo-core" ]
  }

  executable("libbrillo_dbus_data_serialization_fuzzer") {
    sources = [ "brillo/dbus/data_serialization_fuzzer.cc" ]

    configs += [ "//common-mk/common_fuzzer:common_fuzzer" ]

    pkg_deps = [ "libchrome-${libbase_ver}" ]

    include_dirs = [ "../libbrillo" ]

    deps = [ ":libbrillo-core" ]
  }

  executable("libbrillo_http_form_data_fuzzer") {
    sources = [ "brillo/http/http_form_data_fuzzer.cc" ]

    configs += [ "//common-mk/common_fuzzer:common_fuzzer" ]

    pkg_deps = [ "libchrome-${libbase_ver}" ]

    include_dirs = [ "../libbrillo" ]

    deps = [
      ":libbrillo-http",
      ":libbrillo-streams",
    ]
  }
}

copy("libinstallattributes-includes") {
  sources = [ "install_attributes/libinstallattributes.h" ]
  outputs =
      [ "${root_gen_dir}/include/install_attributes/{{source_file_part}}" ]
}

copy("libpolicy-includes") {
  sources = [
    "policy/device_policy.h",
    "policy/device_policy_impl.h",
    "policy/libpolicy.h",
    "policy/mock_device_policy.h",
    "policy/mock_libpolicy.h",
    "policy/policy_util.h",
    "policy/resilient_policy_util.h",
  ]
  outputs = [ "${root_gen_dir}/include/policy/{{source_file_part}}" ]
}
