/*
 * NAME
 *      c++ - the C++ compiler cookbook
 *
 * DESCRIPTION
 *      This cookbook describes how to work with C++ files.
 *      Include file dependencies are automatically determined.
 *
 * RECIPES
 *      %.o: %.cpp      make object files form C++ source files
 *      %.o: %.cc       make object files form C++ source files
 *      %.o: %.c++      make object files form C++ source files
 *
 * VARIABLES
 *      c_incl          The C++ include dependency sniffer command.
 *                      Not altered if already defined.
 *      c++             The C++ compiler command
 *                      Not altered if already defined.
 *      c++_flags       options to pass to the C++ compiler command
 *                      Not altered if already defined.
 *                      The default is "-O".
 *      c++_include_flags Options passed to the C++ compiler and c_incl
 *                      controlling include file searching.
 *                      Not altered if already defined.
 *                      The default is empty.
 *      c++_src         C++ source files in the current directory.
 *      dot_src         Source files constructable in the current directory
 *                      (unioned with existing setting, if necessary).
 *      dot_obj         Object files constructable in the current directory
 *                      (unioned with existing setting, if necessary).
 *      dot_clean       Files which may be removed from the current directory
 *                      in a clean target.
 *
 * SEE ALSO
 *      program         The program cookbook:
 *         ld              The linker program
 *         ld_flags        The linker flags, NOT libraries
 *         ld_libraries    The linker flags (-L, -l) for libraries
 *
 * MANIFEST: cookbook for using C++
 * Copyright (C) 2002, 2007 Peter Miller
 */

#pragma once

if [not [defined c_incl]] then
        c_incl = [find_command c_incl];
if [not [defined c++]] then
        c++ = g++;
if [not [defined c++_flags]] then
        c++_flags = -O;
if [not [defined c++_include_flags]] then
        c++_include_flags = ;
if [not [defined c++_link_flags]] then
        c++_link_flags = ;
c++_src = [glob "*.cpp" "*.cc" "*.c++" ];
if [not [defined dot_src]] then
        dot_src = ;
dot_src =
        [stringset
            [dot_src] [c++_src]
        -
            [fromto %.cpp %.s
            [fromto %.c++ %.s
            [fromto %.cc %.s
                [c++_src]
            ]]]
        ];
if [not [defined dot_obj]] then
        dot_obj = ;
dot_obj =
        [stringset
            [dot_obj]

            [fromto %.cpp %.o
            [fromto %.c++ %.o
            [fromto %.cc %.o
                [c++_src]
            ]]]
        ];
if [not [defined dot_clean]] then
        dot_clean = ;
dot_clean =
        [stringset
                [dot_clean]
                [fromto %.cpp %.o
                [fromto %.cc %.o
                [fromto %.c++ %.o
                    [c++_src]
                ]]]
                [fromto %.cpp %.s
                [fromto %.cc %.s
                [fromto %.c++ %.s
                    [c++_src]
                ]]]
        ];

%.o: %.cpp
{
        [c++] [c++_include_flags] [c++_flags]
                [addprefix "-I" [search_list]]
                -o [target]
                -c [resolve %.cpp];
}

%.o: %.cc
{
        [c++] [c++_include_flags] [c++_flags]
                [addprefix "-I" [search_list]]
                -o [target]
                -c [resolve %.cc];
}

%.o: %.c++
{
        [c++] [c++_include_flags] [c++_flags]
                [addprefix "-I" [search_list]]
                -o [target]
                -c [resolve %.c++];
}

/*
 * if the c_incl command is available, then check dependencies
 */
#if [c_incl]
        %.cpp.d: %.cpp
        {
                [c_incl] -nc -ns -nrec
                        [c++_include_flags]
                        [resolve %.cpp]
                        [addprefix "-I" [search_list]]
                        -prefix "'cascade %.cpp ='"
                        -suffix "';'"
                        [addprefix "-rlp=" [split ":" [search_list]]]
                        -o [target];
        }
        %.cc.d: %.cc
        {
                [c_incl] -nc -ns -nrec
                        [c++_include_flags]
                        [resolve %.cc]
                        [addprefix "-I" [search_list]]
                        -prefix "'cascade %.cc ='"
                        -suffix "';'"
                        [addprefix "-rlp=" [split ":" [search_list]]]
                        -o [target];
        }
        %.c++.d: %.c++
        {
                [c_incl] -nc -ns -nrec
                        [c++_include_flags]
                        [resolve %.c++]
                        [addprefix "-I" [search_list]]
                        -prefix "'cascade %.c++ ='"
                        -suffix "';'"
                        [addprefix "-rlp=" [split ":" [search_list]]]
                        -o [target];
        }
        %.h.d: %.h
        {
                [c_incl] -nc -ns -nrec
                        [c++_include_flags]
                        [resolve %.h]
                        [addprefix "-I" [search_list]]
                        -prefix "'cascade %.h ='"
                        -suffix "';'"
                        [addprefix "-rlp=" [split ":" [search_list]]]
                        -o [target];
        }

        c++_dep_files = [addsuffix ".d" [c++_src] [glob "*.h"]];
        dot_clean =
                [stringset
                        [dot_clean]
                        [c++_dep_files]
                ];

        #include-cooked-nowarn [c++_dep_files]
#endif
