# Copyright 2020 The Bazel Authors. All rights reserved.
#
# 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
#
#    http://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.

"""cc_library Starlark implementation replacing native"""

load("//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
load("//cc/common:cc_common.bzl", "cc_common")
load("//cc/common:cc_helper.bzl", "cc_helper")
load("//cc/common:cc_info.bzl", "CcInfo")
load("//cc/common:semantics.bzl", "semantics")
load(":function_providing_rule.bzl", "wrap_starlark_function")

def _cc_library_impl(ctx):
    semantics.validate(ctx, "cc_library")
    cc_helper.check_srcs_extensions(ctx, ALLOWED_SRC_FILES, "cc_library", True)

    semantics.check_cc_shared_library_tags(ctx)

    cc_toolchain = find_cc_toolchain(ctx)
    cc_helper.report_invalid_options(cc_toolchain, ctx.fragments.cpp)

    features = ctx.features
    feature_configuration = cc_common.configure_features(
        ctx = ctx,
        cc_toolchain = cc_toolchain,
        requested_features = features,
        unsupported_features = ctx.disabled_features,
    )

    cc_helper.check_cpp_modules(ctx, feature_configuration)

    precompiled_files = cc_helper.build_precompiled_files(ctx = ctx)

    semantics.validate_attributes(ctx)
    _check_no_repeated_srcs(ctx)

    semantics.check_can_use_implementation_deps(ctx)
    interface_deps = ctx.attr.deps + cc_helper.get_cc_runtimes(ctx, True)
    runtimes_copts = cc_helper.get_cc_runtimes_copts(ctx)
    compilation_contexts = cc_helper.get_compilation_contexts_from_deps(interface_deps)
    implementation_compilation_contexts = cc_helper.get_compilation_contexts_from_deps(ctx.attr.implementation_deps)

    additional_make_variable_substitutions = cc_helper.get_toolchain_global_make_variables(cc_toolchain, feature_configuration)
    additional_make_variable_substitutions.update(cc_helper.get_cc_flags_make_variable(ctx, feature_configuration, cc_toolchain))

    (compilation_context, srcs_compilation_outputs) = cc_common.compile(
        actions = ctx.actions,
        name = ctx.label.name,
        cc_toolchain = cc_toolchain,
        feature_configuration = feature_configuration,
        user_compile_flags = runtimes_copts + cc_helper.get_copts(ctx, feature_configuration, additional_make_variable_substitutions, attr = "copts", requested_features = features),
        conly_flags = cc_helper.get_copts(ctx, feature_configuration, additional_make_variable_substitutions, attr = "conlyopts", requested_features = features),
        cxx_flags = cc_helper.get_copts(ctx, feature_configuration, additional_make_variable_substitutions, attr = "cxxopts", requested_features = features),
        defines = cc_helper.defines(ctx, additional_make_variable_substitutions),
        local_defines = cc_helper.local_defines(ctx, additional_make_variable_substitutions) + cc_helper.get_local_defines_for_runfiles_lookup(ctx, ctx.attr.deps + ctx.attr.implementation_deps),
        includes = cc_helper.include_dirs(ctx, additional_make_variable_substitutions),
        local_includes = cc_helper.include_dirs(ctx, additional_make_variable_substitutions, attr = "local_includes"),
        purpose = "cc_library-compile",
        srcs = cc_helper.get_srcs(ctx),
        module_interfaces = cc_helper.get_cpp_module_interfaces(ctx),
        private_hdrs = cc_helper.get_private_hdrs(ctx),
        public_hdrs = cc_helper.get_public_hdrs(ctx),
        code_coverage_enabled = cc_helper.is_code_coverage_enabled(ctx),
        compilation_contexts = compilation_contexts,
        implementation_compilation_contexts = implementation_compilation_contexts,
        textual_hdrs = ctx.files.textual_hdrs,
        include_prefix = ctx.attr.include_prefix,
        strip_include_prefix = ctx.attr.strip_include_prefix,
        additional_inputs = ctx.files.additional_compiler_inputs,
    )

    precompiled_objects = cc_common.create_compilation_outputs(
        objects = depset(precompiled_files[0]),
        pic_objects = depset(precompiled_files[1]),
    )

    compilation_outputs = cc_common.merge_compilation_outputs(
        compilation_outputs = [precompiled_objects, srcs_compilation_outputs],
    )

    supports_dynamic_linker = cc_common.is_enabled(
        feature_configuration = feature_configuration,
        feature_name = "supports_dynamic_linker",
    )

    create_dynamic_library = (not ctx.attr.linkstatic and
                              supports_dynamic_linker and
                              (not cc_helper.is_compilation_outputs_empty(compilation_outputs) or
                               cc_common.is_enabled(
                                   feature_configuration = feature_configuration,
                                   feature_name = "header_module_codegen",
                               )))

    output_group_builder = {}

    has_compilation_outputs = not cc_helper.is_compilation_outputs_empty(compilation_outputs)
    linking_context = CcInfo().linking_context
    empty_archive_linking_context = CcInfo().linking_context

    linking_contexts = cc_helper.get_linking_contexts_from_deps(ctx.attr.deps)
    linking_contexts.extend(
        cc_helper.get_linking_contexts_from_deps(
            ctx.attr.implementation_deps + cc_helper.get_cc_runtimes(ctx, True),
        ),
    )
    if ctx.file.linkstamp != None:
        linkstamps = []
        linkstamps.append(cc_common.create_linkstamp(
            linkstamp = ctx.file.linkstamp,
            headers = compilation_context.headers,
        ))
        linkstamps_linker_input = cc_common.create_linker_input(
            owner = ctx.label,
            linkstamps = depset(linkstamps),
        )
        linkstamps_linking_context = cc_common.create_linking_context(
            linker_inputs = depset([linkstamps_linker_input]),
        )
        linking_contexts.append(linkstamps_linking_context)

    if has_compilation_outputs:
        dll_name_suffix = ""
        additional_inputs = _filter_linker_scripts(ctx.files.deps) + ctx.files.additional_linker_inputs
        link_variables = {}
        is_windows_enabled = cc_common.is_enabled(feature_configuration = feature_configuration, feature_name = "targets_windows")
        if is_windows_enabled:
            dll_name_suffix = cc_helper.dll_hash_suffix(ctx, feature_configuration, ctx.fragments.cpp)
            generated_def_file = None

            generated_def_file = cc_helper.generate_def_file(
                ctx,
                ctx.file._def_parser,
                compilation_outputs.objects,
                ctx.label.name + dll_name_suffix,
                cc_toolchain,
                feature_configuration,
            )
            if generated_def_file != None:
                output_group_builder["def_file"] = depset([generated_def_file])

            win_def_file = cc_helper.get_windows_def_file_for_linking(ctx, ctx.file.win_def_file, generated_def_file, feature_configuration)
            link_variables["def_file_path"] = win_def_file.path
            additional_inputs.append(win_def_file)

        (
            linking_context,
            linking_outputs,
        ) = cc_common.create_linking_context_from_compilation_outputs(
            actions = ctx.actions,
            name = ctx.label.name,
            compilation_outputs = compilation_outputs,
            cc_toolchain = cc_toolchain,
            feature_configuration = feature_configuration,
            additional_inputs = additional_inputs,
            linking_contexts = linking_contexts,
            user_link_flags = cc_helper.linkopts(ctx, additional_make_variable_substitutions, cc_toolchain),
            alwayslink = ctx.attr.alwayslink,
            disallow_dynamic_library = not create_dynamic_library,
            linked_dll_name_suffix = dll_name_suffix,
            variables_extension = link_variables,
        )
    else:
        linking_outputs = struct(library_to_link = None)

    _add_linker_artifacts_output_groups(output_group_builder, linking_outputs)

    precompiled_libraries = _convert_precompiled_libraries_to_library_to_link(
        ctx,
        cc_toolchain,
        feature_configuration,
        ctx.fragments.cpp.force_pic(),
        precompiled_files,
        ctx.attr.alwayslink,
    )

    if not cc_helper.is_compilation_outputs_empty(compilation_outputs):
        _check_if_link_outputs_colliding_with_precompiled_files(
            ctx,
            linking_outputs,
            precompiled_libraries,
        )

    precompiled_linking_context = cc_helper.build_linking_context_from_libraries(ctx, precompiled_libraries)

    contexts_to_merge = [precompiled_linking_context, empty_archive_linking_context]
    if has_compilation_outputs:
        contexts_to_merge.append(linking_context)
    else:
        user_link_flags = cc_helper.linkopts(ctx, additional_make_variable_substitutions, cc_toolchain)
        linker_scripts = _filter_linker_scripts(ctx.files.deps)
        additional_linker_inputs = ctx.files.additional_linker_inputs
        linker_input = cc_common.create_linker_input(
            owner = ctx.label,
            user_link_flags = user_link_flags,
            additional_inputs = depset(linker_scripts + additional_linker_inputs),
        )
        contexts_to_merge.append(cc_common.create_linking_context(linker_inputs = depset([linker_input])))

        contexts_to_merge.extend(linking_contexts)

    linking_context = cc_common.merge_linking_contexts(
        linking_contexts = contexts_to_merge,
    )

    libraries_to_link = _create_libraries_to_link_list(
        linking_outputs.library_to_link,
        precompiled_libraries,
    )

    linking_context_for_runfiles = cc_helper.build_linking_context_from_libraries(ctx, libraries_to_link)

    cc_native_library_info = cc_helper.collect_native_cc_libraries(
        deps = ctx.attr.deps,
        libraries = libraries_to_link,
    )

    files_builder = []
    if linking_outputs.library_to_link != None:
        artifacts_to_build = linking_outputs.library_to_link
        if artifacts_to_build.static_library != None:
            files_builder.append(artifacts_to_build.static_library)

        if artifacts_to_build.pic_static_library != None:
            files_builder.append(artifacts_to_build.pic_static_library)

        if not cc_common.is_enabled(
            feature_configuration = feature_configuration,
            feature_name = "targets_windows",
        ):
            if artifacts_to_build.resolved_symlink_dynamic_library != None:
                files_builder.append(artifacts_to_build.resolved_symlink_dynamic_library)
            elif artifacts_to_build.dynamic_library != None:
                files_builder.append(artifacts_to_build.dynamic_library)

            if artifacts_to_build.resolved_symlink_interface_library != None:
                files_builder.append(artifacts_to_build.resolved_symlink_interface_library)
            elif artifacts_to_build.interface_library != None:
                files_builder.append(artifacts_to_build.interface_library)

    if hasattr(compilation_outputs, "gcno_files"):
        gcno_files = compilation_outputs.gcno_files()
    else:
        gcno_files = compilation_outputs._gcno_files
    if hasattr(compilation_outputs, "pic_gcno_files"):
        pic_gcno_files = compilation_outputs.pic_gcno_files()
    else:
        pic_gcno_files = compilation_outputs._pic_gcno_files
    instrumented_files_info = cc_helper.create_cc_instrumented_files_info(
        ctx = ctx,
        cc_config = ctx.fragments.cpp,
        cc_toolchain = cc_toolchain,
        feature_configuration = feature_configuration,
        metadata_files = gcno_files + pic_gcno_files,
    )

    runfiles_list = []
    for data_dep in ctx.attr.data:
        if data_dep[DefaultInfo].data_runfiles.files:
            runfiles_list.append(data_dep[DefaultInfo].data_runfiles)
        else:
            # This branch ensures interop with custom Starlark rules following
            # https://bazel.build/extending/rules#runfiles_features_to_avoid
            runfiles_list.append(ctx.runfiles(transitive_files = data_dep[DefaultInfo].files))
            runfiles_list.append(data_dep[DefaultInfo].default_runfiles)

    for src in ctx.attr.srcs:
        runfiles_list.append(src[DefaultInfo].default_runfiles)

    for dep in ctx.attr.deps:
        runfiles_list.append(dep[DefaultInfo].default_runfiles)

    for dep in ctx.attr.implementation_deps:
        runfiles_list.append(dep[DefaultInfo].default_runfiles)

    runfiles = ctx.runfiles().merge_all(runfiles_list)

    default_runfiles = ctx.runfiles(files = cc_helper.get_dynamic_libraries_for_runtime(linking_context_for_runfiles, True))
    default_runfiles = runfiles.merge(default_runfiles)

    data_runfiles = ctx.runfiles(files = cc_helper.get_dynamic_libraries_for_runtime(linking_context_for_runfiles, False))
    data_runfiles = runfiles.merge(data_runfiles)

    current_output_groups = cc_helper.build_output_groups_for_emitting_compile_providers(
        compilation_outputs,
        compilation_context,
        ctx.fragments.cpp,
        cc_toolchain,
        feature_configuration,
        ctx,
        generate_hidden_top_level_group = True,
    )
    providers = []

    providers.append(DefaultInfo(
        files = depset(files_builder),
        default_runfiles = default_runfiles,
        data_runfiles = data_runfiles,
    ))

    debug_context = cc_helper.merge_cc_debug_contexts(
        compilation_outputs,
        cc_helper.get_providers(ctx.attr.deps + ctx.attr.implementation_deps, CcInfo),
    )
    cc_info = CcInfo(
        compilation_context = compilation_context,
        linking_context = linking_context,
        debug_context = debug_context,
        cc_native_library_info = cc_native_library_info,
    )

    merged_output_groups = cc_helper.merge_output_groups(
        [current_output_groups, output_group_builder],
    )

    providers.append(cc_info)
    providers.append(OutputGroupInfo(**merged_output_groups))
    providers.append(instrumented_files_info)

    return providers

def _add_linker_artifacts_output_groups(output_group_builder, linking_outputs):
    archive_file = []
    dynamic_library = []

    lib = linking_outputs.library_to_link

    if lib == None:
        return

    if lib.static_library != None:
        archive_file.append(lib.static_library)
    elif lib.pic_static_library != None:
        archive_file.append(lib.pic_static_library)

    if lib.resolved_symlink_dynamic_library != None:
        dynamic_library.append(lib.resolved_symlink_dynamic_library)
    elif lib.dynamic_library != None:
        dynamic_library.append(lib.dynamic_library)

    if lib.resolved_symlink_interface_library != None:
        dynamic_library.append(lib.resolved_symlink_interface_library)
    elif lib.interface_library != None:
        dynamic_library.append(lib.interface_library)

    output_group_builder["archive"] = depset(archive_file)
    output_group_builder["dynamic_library"] = depset(dynamic_library)

def _convert_precompiled_libraries_to_library_to_link(
        ctx,
        cc_toolchain,
        feature_configuration,
        force_pic,
        precompiled_files,
        alwayslink):
    static_libraries = _build_map_identifier_to_artifact(precompiled_files[2])
    pic_static_libraries = _build_map_identifier_to_artifact(precompiled_files[3])
    alwayslink_static_libraries = _build_map_identifier_to_artifact(precompiled_files[4])
    alwayslink_pic_static_libraries = _build_map_identifier_to_artifact(precompiled_files[5])
    dynamic_libraries = _build_map_identifier_to_artifact(precompiled_files[6])

    libraries = []

    identifiers_used = {}
    static_libraries_it = []
    static_libraries_it.extend(static_libraries.items())
    static_libraries_it.extend(alwayslink_static_libraries.items())
    for identifier, v in static_libraries_it:
        static_library = None
        pic_static_library = None
        dynamic_library = None

        has_pic = identifier in pic_static_libraries
        has_always_pic = identifier in alwayslink_pic_static_libraries
        if has_pic or has_always_pic:
            if has_pic:
                pic_static_library = pic_static_libraries[identifier]
            else:
                pic_static_library = alwayslink_pic_static_libraries[identifier]
        if not force_pic or not (has_pic or has_always_pic):
            static_library = v

        if identifier in dynamic_libraries:
            dynamic_library = dynamic_libraries[identifier]

        identifiers_used[identifier] = True

        library = cc_common.create_library_to_link(
            actions = ctx.actions,
            feature_configuration = feature_configuration,
            cc_toolchain = cc_toolchain,
            static_library = static_library,
            pic_static_library = pic_static_library,
            dynamic_library = dynamic_library,
            alwayslink = alwayslink or identifier in alwayslink_static_libraries,
        )
        libraries.append(library)

    pic_static_libraries_it = []
    pic_static_libraries_it.extend(pic_static_libraries.items())
    pic_static_libraries_it.extend(alwayslink_pic_static_libraries.items())
    for identifier, v in pic_static_libraries_it:
        if identifier in identifiers_used:
            continue

        pic_static_library = v
        if identifier in dynamic_libraries:
            dynamic_library = dynamic_libraries[identifier]

        identifiers_used[identifier] = True

        library = cc_common.create_library_to_link(
            actions = ctx.actions,
            feature_configuration = feature_configuration,
            cc_toolchain = cc_toolchain,
            pic_static_library = pic_static_library,
            alwayslink = alwayslink or identifier in alwayslink_static_libraries,
        )
        libraries.append(library)

    for identifier, v in dynamic_libraries.items():
        if identifier in identifiers_used:
            continue

        dynamic_library = dynamic_libraries[identifier]

        library = cc_common.create_library_to_link(
            actions = ctx.actions,
            feature_configuration = feature_configuration,
            cc_toolchain = cc_toolchain,
            dynamic_library = dynamic_library,
        )
        libraries.append(library)

    return libraries

def _build_map_identifier_to_artifact(artifacts):
    libraries = {}
    for artifact in artifacts:
        identifier = _identifier_of_artifact(artifact)
        if identifier in libraries:
            fail(
                "Trying to link twice a library with the same identifier '{}',".format(identifier) +
                "files: {} and {}".format(
                    artifact.short_path,
                    libraries[identifier].short_path,
                ),
                attr = "srcs",
            )
        libraries[identifier] = artifact
    return libraries

def _identifier_of_artifact(artifact):
    name = artifact.short_path
    for pic_suffix in [".pic.a", ".nopic.a", ".pic.lo"]:
        if name.endswith(pic_suffix):
            return name[:len(name) - len(pic_suffix)]

    return name[:len(name) - len(artifact.extension) - 1]

def _identifier_of_library(library):
    if library.static_library != None:
        return _identifier_of_artifact(library.static_library)
    if library.pic_static_library != None:
        return _identifier_of_artifact(library.pic_static_library)
    if library.dynamic_library != None:
        return _identifier_of_artifact(library.dynamic_library)
    if library.interface_library != None:
        return _identifier_of_artifact(library.interface_library)

    return None

def _create_libraries_to_link_list(current_library, precompiled_libraries):
    libraries = []
    libraries.extend(precompiled_libraries)
    if current_library != None:
        libraries.append(current_library)

    return libraries

def _filter_linker_scripts(files):
    linker_scripts = []
    for file in files:
        extension = "." + file.extension
        if extension in LINKER_SCRIPT:
            linker_scripts.append(file)
    return linker_scripts

def _check_if_link_outputs_colliding_with_precompiled_files(ctx, linking_outputs, precompiled_libraries):
    identifier = _identifier_of_library(linking_outputs.library_to_link)
    for precompiled_library in precompiled_libraries:
        precompiled_library_identifier = _identifier_of_library(precompiled_library)
        if precompiled_library_identifier == identifier:
            fail("Can't put library with identifier '{}' into the srcs of a cc_library with".format(identifier) +
                 " the same name ({}) which also contains other code or objects to link".format(
                     ctx.label.name,
                 ))

def _check_no_repeated_srcs(ctx):
    seen = {}
    for target in ctx.attr.srcs:
        if DefaultInfo in target:
            for file in target[DefaultInfo].files.to_list():
                extension = "." + file.extension
                if extension not in cc_helper.extensions.CC_HEADER:
                    if extension in cc_helper.extensions.CC_AND_OBJC:
                        if file.path in seen:
                            if seen[file.path] != target.label:
                                fail("Artifact '{}' is duplicated (through ".format(file.path) +
                                     "'{}' and '{}')".format(str(seen[file.path]), str(target.label)))
                        seen[file.path] = target.label

ALLOWED_SRC_FILES = []
ALLOWED_SRC_FILES.extend(cc_helper.extensions.CC_SOURCE)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.C_SOURCE)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.CC_HEADER)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.ASSEMBLER_WITH_C_PREPROCESSOR)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.ASSEMBLER)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.ARCHIVE)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.PIC_ARCHIVE)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.ALWAYSLINK_LIBRARY)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.ALWAYSLINK_PIC_LIBRARY)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.SHARED_LIBRARY)

SRCS_FOR_COMPILATION = []
SRCS_FOR_COMPILATION.extend(cc_helper.extensions.CC_SOURCE)
SRCS_FOR_COMPILATION.extend(cc_helper.extensions.C_SOURCE)
SRCS_FOR_COMPILATION.extend(cc_helper.extensions.ASSEMBLER_WITH_C_PREPROCESSOR)
SRCS_FOR_COMPILATION.extend(cc_helper.extensions.ASSEMBLER)

ALLOWED_SRC_FILES.extend(cc_helper.extensions.OBJECT_FILE)
ALLOWED_SRC_FILES.extend(cc_helper.extensions.PIC_OBJECT_FILE)

LINKER_SCRIPT = [".ld", ".lds", ".ldscript"]

cc_library_impl = _cc_library_impl
cc_library_impl_wrapper = wrap_starlark_function(_cc_library_impl)
