void buildHeader(string destination, string class, list iFiles)
{
    list record;
    string line;

    echo(OFF);

    run("rm -f " + g_cwd + g_tmphdr + class);
    printf("Header ", g_tmphdr, class, "\n");

    while (1)
    {
        record = fgets(class, (int)record[1]);
        if (!record)
            break;

        line = record[0];

        if (strfind(line, "#include \"") != 0)
            fprintf(destination, line);
        else
            exec("cat " + strtok(line, "\"")[1] + " >> " + destination);
    }

    echo(ECHO_COMMANDS);
}

void iFiles(string class)
{
    int idx;
    string destination;
    list iFiles;
    int recreate = 0;

    destination = g_cwd + g_tmphdr + class;     

    chdir(class);
                                        // the destination file name

    iFiles = makelist("*.f");           // create list of all f-files

    if (class newer destination)
        recreate = 1;
    else
    {
        for (idx = sizeof(iFiles); idx--; )
        {
            if (iFiles[idx] newer destination)
            {
                recreate = 1;
                break;
            }
        }
    }

    if (recreate)
        buildHeader(destination, class, iFiles);

    chdir(g_cwd);
}    
    
void cpHeaders()
{
    int idx;
    string file;
    string class;
    
    for (idx = g_nClasses; idx--; )
        iFiles(g_classes[idx]);
}

void static_library(string library)
{
    if (sizeof(makelist("*/oa/*.o")))
    {
        printf("\n"
               "Creating static library ", library, "\n");

        run("ar cru " + library + " */oa/*.o");
        run("ranlib " + library);
        run("rm */oa/*.o");
    }
}

void shared_library(string destDir, string libso, string libsoshared, 
                    int strip)
{
    string libsomajor;
    string gxx;

    gxx = g_cxx + " " + g_copt;
    
    if (sizeof(makelist("*/os/*.o")))
    {
        printf("\n"
               "Creating shared library ", libso, "\n");

        libsomajor  = libso + "." + element(0, strtok(g_version, "."));

        run(gxx +  
                    " " + setOpt(LDFLAGS, "LDFLAGS") +
                    " -shared -Wl,--as-needed,"
                    "-z,defs,-soname," + 
                    libsomajor +
                    " -o " + destDir + libsoshared +
                    " */os/*.o " +
                    g_sharedLibReq);
    
        chdir(destDir);
    
        if (strip)
            run("strip --strip-unneeded " + libsoshared);

        run("chmod -x " + libsoshared);
        
        run("ln -sf " + libsoshared + " " + libsomajor);
        run("ln -sf " + libsomajor  + " " + libso);
    
//        run("rm -f */os/*");

        chdir(g_cwd);
    }
}

void libraries(string libname, int all, int strip)
{
    string libso;
    string libsoshared;
    string staticLib;

    staticLib = g_tmplib + "lib" LIBRARY ".a";

    addClasses("CLASSES");
    special(1, all);

    md(g_tmplib + " " + g_tmphdr);

    cpHeaders();

    g_copt += " -isystem tmp";

    library("oa", staticLib);               // compile for static lib.
    static_library(staticLib);              // build static library

#ifndef ONLY_STATIC
    libso = "lib" LIBRARY ".so";
    libsoshared = libso + "." + g_version;

    g_copt += " -fPIC";
                                          // adds option for shared lib

    library("os", g_tmplib + libsoshared);      // compile the shared lib

    shared_library(g_tmplib, libso, libsoshared, strip);
#endif

    exit(0);
}

