/*
 * This file is part of the Score-P software (http://www.score-p.org)
 *
 * Copyright (c) 2009-2013,
 * RWTH Aachen University, Germany
 *
 * Copyright (c) 2009-2013,
 * Gesellschaft fuer numerische Simulation mbH Braunschweig, Germany
 *
 * Copyright (c) 2009-2014,
 * Technische Universitaet Dresden, Germany
 *
 * Copyright (c) 2009-2013,
 * University of Oregon, Eugene, USA
 *
 * Copyright (c) 2009-2013, 2017, 2023-2024,
 * Forschungszentrum Juelich GmbH, Germany
 *
 * Copyright (c) 2009-2013,
 * German Research School for Simulation Sciences GmbH, Juelich/Aachen, Germany
 *
 * Copyright (c) 2009-2013,
 * Technische Universitaet Muenchen, Germany
 *
 * This software may be modified and distributed under the terms of
 * a BSD-style license.  See the COPYING file in the package base
 * directory for details.
 *
 */

/**
 * @file
 *
 * Declares classes for the representation and analysis of library dependencies
 */

#ifndef OTF2_CONFIG_DATA_HPP
#define OTF2_CONFIG_DATA_HPP

#include <map>
#include <deque>
#include <string>
#include <library_data.hpp>


/**
 * A class to store and analyze the dependencies from libraries. To generate
 * the dependecies, Makefile variables are parsed and header files are generated,
 * see build-config/common/Makefile.rpaths.inc.am. Note that we take care of
 * omitting known linker and loader search paths in GetLDFlags(), GetLTLDFlags()
 * and GetRpathFlags().
 */
class otf2_config_data
{
    // ------------------------------------- Public types
public:

    /**
     * Constructs the library dependecies
     */
    otf2_config_data( void );

    /**
     * Destructor
     */
    virtual
    ~otf2_config_data();

    /**
     * Returns the string containing the @a input_libs and its dependencies.
     * @param input_libs  A list of libraries, that should be linked.
     */
    std::string
    GetLibraries( const std::deque<std::string>& inputLibs );

    /**
     * Returns the duplicate-free string containing the -L library path flags
     * for the @a input_libs and its dependencies. Known linker search paths
     * are omitted.
     * @param libs     A list of library names.
     */
    std::string
    GetLDFlags( const std::deque<std::string>& libs );

    /**
     * Returns the duplicate-free string containing the -L and -R flags for
     * libtool consumption for the @a input_libs and their dependencies.
     * Known linker and loader search paths are omitted.
     * If LD_RUN_PATH is set at execution time of otf2-config, its
     * directories are appended as -R<dir>.
     * @param libs     A list of library names.
     */
    std::string
    GetLTLDFlags( const std::deque<std::string>& libs );

    /**
     * Returns the duplicate-free string containing the rpath flags
     * for the @a libs and its dependencies (usually -Wl,-rpath -Wl,<dir>).
     * Known loader search paths are omitted.
     * If LD_RUN_PATH is set at execution time of otf2-config, its
     * directories are appended.
     * @param libs      A list of library names.
     */
    std::string
    GetRpathFlags( const std::deque<std::string>& libs );

    /**
     * Construct rpath construction flags
     */
    void
    prepare_rpath_flags( void );

    /** Make string with compiler or linker flags compatible to CUDA
     *  compiler requirements.
     *
     *  @param str              String to be processed.
     *
     *  @return Returns string with compiler or linker flags that can be
     *          passes to CUDA compiler.
     */
    std::string
    prepare_string( const std::string& str );

    // ------------------------------------- Public members
public:

    std::string m_rpath_head;
    std::string m_rpath_delimiter;
    std::string m_rpath_tail;

    std::string m_cc;
    std::string m_cppflags;
    std::string m_datadir;
    std::string m_pythonpath;
    std::string m_python_support;
    bool        m_use_rpath_flag;
    std::string m_rpath_flag_cc;
    std::string m_wl_flag;
    std::string m_aix_libpath;
    std::string m_sys_lib_search_path;
    std::string m_sys_lib_dlsearch_path;
    bool        m_have_sionlib_support;

    std::map< std::string, LibraryData> m_library_objects;

private:

    /**
     * Remove known linker search paths from @p input.
     */
    std::deque<std::string>
    remove_linker_search_paths( const std::deque<std::string>& input );

    /**
     * Remove known loader search paths from @p input.
     */
    std::deque<std::string>
    remove_loader_search_paths( const std::deque<std::string>& input );

    /**
     * Remove paths from @p input that are part of @p remove.
     */
    std::deque<std::string>
    remove_paths( const std::deque<std::string>& input,
                  const std::deque<std::string>& remove );

    /**
     * Helper function to make sure @a libs exist in m_library_objects,
     * die otherwise.
     * @param libs a container of library names
     */
    void
    assert_lib_objects_exist( const std::deque<std::string>& libs ) const;

    /**
     * Helper function to collect a container of all libdirs needed for
     * linking all @a libs. Intended to be used from GetLDFlags(),
     * GetLTLDFlags(), and GetRpathFlags().
     */
    std::deque<std::string>
    get_libdirs( const std::deque<std::string>& libs );

    /**
     * Return the contents of the environment variable LD_RUN_PATH as
     * container of strings, ommitting system linker search paths,
     * non-absolute paths and those containing whitespace.
     */
    std::deque<std::string>
    get_ld_run_path();
};

otf2_config_data*
otf2_config_get_backend_data( void );

#ifdef CROSS_BUILD

otf2_config_data*
otf2_config_get_frontend_data( void );

#else

#define otf2_config_get_frontend_data() \
    otf2_config_get_backend_data()

#endif

#endif /* OTF2_CONFIG_DATA_HPP */
