Commits

rubenvb committed 8bc7ac4

Ugly, ugly WIP

Comments (0)

Files changed (22)

Ambrosia/Include/commandline.h

 #include "global.h"
 
 // libAmbrosia includes
-#include "Ambrosia/Configuration/ambrosia_config.h"
 #include "Ambrosia/typedefs.h"
 
+// Foward declarations
+libambrosia_namespace_begin
+class ambrosia_config;
+class file_cache;
+class project;
+libambrosia_namespace_end
+
 ambrosia_namespace_begin
 
-bool apply_commandline_options( const string_vector &options, lib::project &project );
+void apply_commandline_options( const string_vector &options, lib::project &project,
+                                lib::file_cache &files);
 
-bool add_build_target( const std::string &target, lib::project &project );
+bool add_build_target( const std::string &target );
 
 void set_internal_option( const std::string &option, const std::string &value,
                           lib::project &project );

Ambrosia/Source/begin.cpp

     // if project file is not yet set, search current directory
     if( lib::s_ambrosia_config.project_file().empty() )
     {
-        const string project_file = lib::find_nectar_file( "." );
+        /*const string project_file = lib::find_nectar_file( "." );
         if( !project_file.empty() )
         {
             //debug(2) << "begin::Project file found in current directory \'.\': " << project_file << ".\n";
             lib::s_ambrosia_config.set_project_file( project_file );
         }
         else if( !lib::error_status() )
-            lib::emit_error( "No project file found in specified path or current directory." );
+            lib::emit_error( "No project file found in specified path or current directory." );*/
     }
     //debug(1) << "begin::Checking if project file was found.\n";
     // Ensure that a valid project file has been found

Ambrosia/Source/commandline.cpp

 /* "Ambrosia/Configuration/ambrosia_config.h" */
 #include "Ambrosia/debug.h"
     using libambrosia::debug;
+#include "Ambrosia/Error/commandline_error.h"
+#include "Ambrosia/Error/soft_error.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/nectar.h"
 #include "Ambrosia/project.h"
-#include "Ambrosia/status.h"
+#include "Ambrosia/Error/error.h"
+
+// C-ish includes
+#include <cassert>
 
 // C++ includes
 #include <algorithm>
 
 ambrosia_namespace_begin
 
-bool apply_commandline_options( const string_vector &arguments, lib::project &project )
+void apply_commandline_options( const string_vector &arguments, lib::project &project,
+                                lib::file_cache &files )
 {
     // Debug output
     std::for_each( arguments.begin(), arguments.end(),
 
     // Execution ending arguments
     if( lib::contains(arguments, string("-v")) || lib::contains(arguments, "-version") )
-        return false; // version info already printed, quit immediately
+        throw lib::soft_error( "Execution stopped after request for version output." );
     else if( lib::contains(arguments, "-h") || lib::contains(arguments, "-help") )
     {
         print_help_information();
-        return false; // quit immediately
+        throw lib::soft_error( "Execution stopped after request for help output." );
     }
 
     // Options to be filled in, with default values, if any
                     m_first_dashless_argument = false;
                     debug(debug::commandline) << "begin::Possible project file or directory: \'" << current << "\'.\n";
 
-                    lib::find_project_file( current, project.config() );
-                    if( lib::error_status() )
-                        return true;
+                    files.find_project_file( current, lib::project::configuration );
 
                     // if project_file is still empty, "current" is really a target name to be built, skip to below next else
-                    if( project.config().project_file().empty() )
+                    if( lib::project::configuration.project_file().empty() )
                         goto add_target;
                 }
                 else
                 {
                     add_target:
-                    if( !add_build_target(current, project) )
-                        return true;
+                    if( !add_build_target(current) )
+                        throw lib::commandline_error( "Unable to add target " + current + " to be built.",
+                                                      std::distance(arguments.begin(),it) );
                 }
                 break;
             case 1:
                 if( current[0] == '-' )
                 {
-                    if( "-h" == current || "-help" == current )
-                    {
-                        debug(debug::commandline) << "begin::Printing help information.\n";
-                        ambrosia::print_help_information();
-                        return false;
-                    }
-                    else if( "-v" == current || "-version" == current)
-                    {
-                        debug(debug::commandline) << "begin::Printing version information.\n";
-                        ambrosia::print_version_information();
-                        return false;
-                    }
                     const string::size_type index = current.find( "=",1 );
                     if( index == string::npos || index == current.size()-1 )
-                    {
-                        lib::emit_error( "Ambrosia internal options must be set by \'-option=value\' type arguments." );
-                        return true;
-                    }
+                        throw lib::commandline_error( "Ambrosia internal options must be set by \'-option=value\' type arguments.",
+                                                      std::distance(arguments.begin(),it) );
+
                     const string option( current.substr(1,index-1) );
                     const string value( current.substr(index+1, string::npos) );
-                    set_internal_option( option, value, project );
-                    // check for any error that may have happened in the above call to libAmbrosia
-                    if( lib::error_status() )
-                        return true;
+                    project.set_internal_option( option, value );
                 }
                 else if( current[0] == ':' )
                 {
-                    if( !add_configuration_options(current.substr(1), project.config()) )
-                        return true;
+                    if( !add_configuration_options(current.substr(1), lib::project::configuration) )
+                        throw lib::commandline_error( "Cannot set configuration option: " + current,
+                                                      std::distance(arguments.begin(), it) );
                 }
                 break;
             case 2:
                 //  store in a string_map?
                 break;
             default:
-                lib::emit_error( "Invalid commandline argument: \'" + current + "\'." );
-                return true;
+                throw lib::commandline_error( "Invalid commandline argument: " + current,
+                                              std::distance(arguments.begin(), it) );
         }
     }
     // if project file is not yet set, search current directory
-    if( project.config().project_file().empty() )
+    if( lib::project::configuration.project_file().empty() )
     {
-        const string project_file = lib::find_nectar_file( "." );
-        if( !project_file.empty() )
+        if( files.find_project_file(".", lib::project::configuration) )
         {
-            debug(debug::commandline) << "begin::Project file found in current directory \'.\': " << project_file << ".\n";
+            debug(debug::commandline) << "begin::Project file found in current directory \'.\': "
+                                      << lib::project::configuration.project_file() << ".\n";
             lib::emit_warning( "Ambrosia does not recommend an in-source build." );
-            project.config().set_source_directory( "" );
-            project.config().set_project_file( project_file );
         }
-        else if( !lib::error_status() )
-            lib::emit_error( "No project file found in specified path or current directory." );
+        else
+            throw lib::error( "No project file found in specified path or current directory." );
     }
     debug(debug::commandline) << "commandline::apply_commandline_options::Checking if project file was found.\n";
     // Ensure that a valid project file has been found
-    if( lib::file_exists(project.config().path_to_project_file()) )
-        return true;
-    else
-    {
-        lib::emit_error( "No project file was found. Please specify a project file or a directory containing a single project file." );
-        return true;
-    }
-    return false; // clean up the above and this
+    assert( lib::file_exists(lib::project::configuration.path_to_project_file()) );
 }
 
-bool add_build_target( const string &target, lib::project &project )
+bool add_build_target( const string &target )
 {
     // TODO: fixme: this function does wrong things
     const string::size_type index = target.find( ":" );
     if( index == string::npos )
     {
         debug(debug::commandline) << "commandline::add_build_target::Target to be built: " << target << ".\n";
-        project.config().add_target_config_options( target, string_set() );
+        lib::project::configuration.add_target_config_options( target, string_set() );
     }
     else
     {
             if( options.insert(temp).second == false )
                 duplicates.insert( temp );
         }
-        project.config().add_target_config_options( target_name, options );
+        lib::project::configuration.add_target_config_options( target_name, options );
     }
     return true;
 }
 
-void set_internal_option( const string &option, const string &value,
-                          lib::project &project )
-{
-    debug(debug::commandline) << "commandline::set_internal_option::Ambrosia internal option: " << option
-                              << " with value " << value << " being set.\n";
-
-    if( "cross" == option )
-    {
-        debug(debug::commandline) << "commandline::set_internal_option::Cross-compiling for "
-                                  << value << ".\n";
-        project.config().set_ambrosia_cross( value );
-    }
-    #ifdef AMBROSIA_DEBUG
-    else if( "d" == option || "debug" == option )
-    {
-        const uint32_t level = lib::from_string<uint32_t>( value );
-        // check validity, partial check on input as well
-        if( level > lib::s_max_debug_level )//|| level < 0 )
-            lib::emit_error( "Debug level must be a number between 0 and 9." );
-        debug(debug::always) << "begin::Setting debug level to " << level << ".\n";
-        debug::s_level = static_cast<debug::type>(level);
-    }
-    #endif // AMBROSIA_DEBUG
-    else if( "gnu-prefix" == option )
-    {
-        debug(debug::commandline) << "commandline::set_internal_option::Cross-compiling with GNU prefix "
-                                  << value << ".\n";
-        project.config().set_gnu_prefix( value );
-    }
-    else
-        lib::emit_error( "Unknown option passed to Ambrosia: \n\t-" + option + "=" + value );
-}
-
 bool add_configuration_options( const string &options, lib::ambrosia_config &/*config*/ )
 {
     debug(debug::commandline) << "commandline::addd_configuration_options::Target configuration option: "

Ambrosia/Source/main.cpp

 using namespace ambrosia;
 
 // libAmbrosia includes
+#include "Ambrosia/Error/error.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/project.h"
-    using libambrosia::project;
 
 // C-ish includes
 #include <cstdlib>
 // C++ includes
 #include <iomanip>
 #include <iosfwd>
+#include <iostream>
 #include <iterator>
 #include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
 
+using namespace std;
+
 int main( int argc, char* argv[] )
 try {
     // Welcome message
     print_version_information();
 
-    project project;
-
-    apply_commandline_options( string_vector(argv+1, argv+argc), project );
-
+    lib::file_cache file_cache;
+    lib::project project( file_cache );
 
+    apply_commandline_options( string_vector(argv+1, argv+argc), project, file_cache );
 
     /*state* current_state = new ambrosia::begin( argc, argv );
     // Main event loop
     //     << "full_directory_name() was called " << s_full_directory_name_calls << " times.\n";
 #endif*/
 }
-catch( ... )
+catch( libambrosia::error &e )
 {
-
+    e.output_message();
+}
+catch( std::exception &e )
+{
+    cout << "something bad happened:\n";
+    cout << e.what();
 }

libAmbrosia/Include/Ambrosia/Error/commandline_error.h

+/**
+  * Ambrosia/Error/commandline_error.h
+  * Commandline errors or errors flowing forth directly from commandline errors.
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+#ifndef AMBROSIA_ERROR_COMMANDLINE_ERROR_H
+#define AMBROSIA_ERROR_COMMANDLINE_ERROR_H
+
+// Global include
+#include "Ambrosia/global.h"
+
+// libAmbrosia includes
+#include "Ambrosia/Error/error.h"
+
+// C++ includes
+/* <string> */
+
+libambrosia_namespace_begin
+
+class commandline_error : public error
+{
+public:
+    commandline_error( const std::string &message, const size_t argument_number );
+
+    void output_message() const;
+
+private:
+    const size_t m_argument_number;
+};
+
+libambrosia_namespace_end
+
+#endif // AMBROSIA_ERROR_COMMANDLINE_ERROR_H

libAmbrosia/Include/Ambrosia/Error/error.h

 {
 public:
     error( const std::string &message, const string_vector &list = string_vector() );
-    virtual ~error() = 0;
+    error( const std::string &message, const file_set &list );
+    virtual ~error();
 
     virtual void output_message() const;
 

libAmbrosia/Include/Ambrosia/Error/soft_error.h

+/**
+  * Ambrosia/Error/nectar_error.cpp
+  * Class implementation.
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+#ifndef AMBROSIA_ERROR_SOFT_ERROR_H
+#define AMBROSIA_ERROR_SOFT_ERROR_H
+
+// Global include
+#include "Ambrosia/global.h"
+
+// libAmbrosia includes
+#include "Ambrosia/Error/error.h"
+
+// C++ includes
+/* <string> */
+
+libambrosia_namespace_begin
+
+class soft_error : public error
+{
+public:
+    soft_error( const std::string &message );
+    ~soft_error();
+};
+
+libambrosia_namespace_end
+
+#endif // AMBROSIA_ERROR_SOFT_ERROR_H

libAmbrosia/Include/Ambrosia/file_cache.h

+/**
+  * Ambrosia/file_cache.h
+  * Cache for filesystem. Stores source and build directories
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+#ifndef AMBROSIA_FILE_CACHE_H
+#define AMBROSIA_FILE_CACHE_H
+
+// Global include
+#include "Ambrosia/global.h"
+
+// libAmbrosia includes
+#include "Ambrosia/typedefs.h"
+
+libambrosia_namespace_begin
+
+// Forward declarations
+class config_base;
+
+class file_cache
+{
+public:
+    file_cache();
+
+    // Finders
+    const std::string find_nectar_file( const std::string &directory, config_base &config );
+    bool find_project_file( const std::string &path, config_base &config );
+
+    // Getters
+    const file_set & get_source_file_set( const std::string &directory );
+
+    // Find the unique relative path to the filename, otherwise return all matching duplicates
+    const file_set find_source_file( const std::string &filename, const config_base &configuration,
+                                     const string_set &directories = string_set() );
+    // Match filename with all directories and match wildcards
+    const file_set match_source_files( const std::string &filename, const config_base &configuration,
+                                       const string_set &directories = string_set() );
+    // Read directory contents from disk (don't complain if already present).
+    void add_source_directory( const std::string &directory = "" );
+    void add_build_directory(const std::string &directory );
+
+private:
+    map_string_file_set m_source_files; // all files in s_ambrosia_config::m_source_directory
+    map_string_file_set m_build_files;  // all files in s_ambrosia_config::m_build_directory
+};
+
+extern file_cache s_file_cache;
+
+libambrosia_namespace_end
+
+#endif // AMBROSIA_FILE_CACHE_H

libAmbrosia/Include/Ambrosia/file_store.h

-/**
-  * Ambrosia/file_store.h
-  * Cache for filesystem. Stores source and build directories
-  *
-  * Author: Ruben Van Boxem
-  *
-  **/
-
-#ifndef AMBROSIA_FILE_STORE_H
-#define AMBROSIA_FILE_STORE_H
-
-// Global include
-#include "Ambrosia/global.h"
-
-// libAmbrosia includes
-#include "Ambrosia/typedefs.h"
-
-libambrosia_namespace_begin
-
-// Forward declarations
-class config_base;
-
-class file_store
-{
-public:
-    file_store();
-
-    // getters
-    const file_set & get_source_file_set( const std::string &directory );
-
-    // Find the unique relative path to the filename, otherwise return all matching duplicates
-    const file_set find_source_file( const std::string &filename, const config_base &configuration,
-                                     const string_set &directories = string_set() );
-    // Match filename with all directories and match wildcards
-    const file_set match_source_files( const std::string &filename, const config_base &configuration,
-                                       const string_set &directories = string_set() );
-    // Read directory contents from disk (don't complain if already present).
-    void add_source_directory( const std::string &directory = "" );
-    void add_build_directory(const std::string &directory );
-
-private:
-    map_string_file_set m_source_files; // all files in s_ambrosia_config::m_source_directory
-    map_string_file_set m_build_files;  // all files in s_ambrosia_config::m_build_directory
-};
-
-extern file_store s_file_store;
-
-libambrosia_namespace_end
-
-#endif // AMBROSIA_FILE_STORE_H

libAmbrosia/Include/Ambrosia/nectar.h

 class target;
 
 // locates a unique .nectar.txt file in file. More than one emits an error
-const std::string find_nectar_file( const std::string &directory );
+//const std::string find_nectar_file( const std::string &directory );
 // finds and sets project file
-bool find_project_file( const std::string &path, ambrosia_config &config );
+//bool find_project_file( const std::string &path, ambrosia_config &config );
 
 // converts all project file content to internal representation, adding to the container where "it" outputs to
 void drink_nectar( const std::string &filename, target_list &targets );

libAmbrosia/Include/Ambrosia/project.h

 
 // libAmbrosia includes
 #include "Ambrosia/Configuration/ambrosia_config.h"
-#include "Ambrosia/file_store.h"
 #include "Ambrosia/status.h"
 #include "Ambrosia/typedefs.h"
 
 libambrosia_namespace_begin
 
+// Forward declarations
+class file_cache;
+
 class project
 {
 public:
-    project();
+    project( file_cache &file_cache );
+
+    static void set_internal_option( const std::string &option, const std::string &value );
 
     // commandline
     void apply_commandline_options( string_vector &arguments);
     void find_project_file();
     void drink_nectar();
 
-    // Getters
-    const ambrosia_config & config() const;
-    ambrosia_config & config();
-    // Setters
-
+    static ambrosia_config configuration;
 
 private:
-    static ambrosia_config m_configuration;
-    static file_store m_file_store;
+    file_cache &m_file_cache;
     project_list m_subprojects;
 };
 

libAmbrosia/Source/Ambrosia/Configuration/ambrosia_config.cpp

 #include "Ambrosia/algorithm.h"
 #include "Ambrosia/debug.h"
 #include "Ambrosia/enum_maps.h"
-#include "Ambrosia/file_store.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/platform.h"
 #include "Ambrosia/status.h"
 

libAmbrosia/Source/Ambrosia/Configuration/config_base.cpp

 #include "Ambrosia/debug.h"
 #include "Ambrosia/enums.h"
 #include "Ambrosia/enum_maps.h"
-#include "Ambrosia/file_store.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/platform.h"
 #include "Ambrosia/status.h"
 
     debug(debug::config) << "config_base::set_source_directory::Setting source directory to: " << source_directory << "\n";
     m_source_directory = source_directory;
     debug(debug::config) << "config_base::set_source_directory::Adding " << m_source_directory << " to s_file_store.\n";
-    s_file_store.add_source_directory( m_source_directory );
+    s_file_cache.add_source_directory( m_source_directory );
     if( !error_status() )
         return true;
     else

libAmbrosia/Source/Ambrosia/Error/commandline_error.cpp

+/**
+  * Ambrosia/Error/commandline_error.h
+  * Class implementation.
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+// Class include
+#include "Ambrosia/Error/commandline_error.h"
+
+// libAmbrosia includes
+#include "Ambrosia/algorithm.h"
+
+// C++ includes
+#include <iostream>
+    using std::cerr;
+/* <string> */
+    using std::string;
+
+libambrosia_namespace_begin
+
+commandline_error::commandline_error( const string &message, const size_t argument_number )
+:   error( message ),
+    m_argument_number( argument_number )
+{   }
+
+void commandline_error::output_message() const
+{
+    cerr << "Commandline error: argument " << to_string(m_argument_number) << ":\n";
+    error::output_message();
+}
+
+libambrosia_namespace_end

libAmbrosia/Source/Ambrosia/Error/error.cpp

 #include "Ambrosia/Error/error.h"
 
 // libAmbrosia includes
-/* "Ambrosia/typedefs.h" */
+#include "Ambrosia/typedefs.h"
 
 // C++ includes
 #include <iostream>
 :   m_message( message ),
     m_list( list )
 {   }
+error::error( const std::string &message, const file_set &list )
+:   m_message( message ),
+    m_list( list.size() )
+{
+    auto dest = m_list.begin();
+    for_each(list.begin(), list.end(), [&](const file& item) { *dest++ = item.first; });
+}
+
 error::~error()
-{   }
+
 
 void error::output_message() const
 {

libAmbrosia/Source/Ambrosia/Error/soft_error.cpp

+/**
+  * Ambrosia/Error/soft_error.cpp
+  * Class implementation.
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+// Class include
+#include "Ambrosia/Error/soft_error.h"
+
+// C++ includes
+/* <string> */
+    using std::string;
+
+libambrosia_namespace_begin
+
+soft_error::soft_error( const string &message )
+:   error( message )
+{   }
+soft_error::~soft_error()
+{   }
+
+libambrosia_namespace_end

libAmbrosia/Source/Ambrosia/file_cache.cpp

+/**
+  * Ambrosia/file_cache.cpp
+  * Class implementation.
+  *
+  * Author: Ruben Van Boxem
+  *
+  **/
+
+// Class include
+#include "Ambrosia/file_cache.h"
+
+// libAmbrosia includes
+#include "Ambrosia/algorithm.h"
+#include "Ambrosia/Configuration/ambrosia_config.h"
+#include "Ambrosia/debug.h"
+#include "Ambrosia/Error/error.h"
+#include "Ambrosia/platform.h"
+#include "Ambrosia/status.h"
+
+// C++ includes
+#include <stdexcept>
+    using std::logic_error;
+/* <string> */
+    using std::string;
+/* <utility> */
+    using std::pair;
+
+libambrosia_namespace_begin
+
+//TODO:REMOVE
+file_cache s_file_cache; // declared in global.h
+
+file_cache::file_cache()
+:   m_source_files(),
+    m_build_files()
+{   }
+
+const string file_cache::find_nectar_file( const string &directory, config_base &config )
+{
+    debug(debug::files) << "nectar::find_nectar_file called for: " << directory << ".\n";
+    config.set_source_directory( directory );
+    file_set candidates = find_source_file( "*.nectar.txt", config );
+    switch( candidates.size() )
+    {
+        case 0:
+            throw error( "No *.nectar.txt file found in " + directory );
+        case 1:
+            return (*candidates.begin()).first; // first = filename, second = modified
+        default:
+            throw error( "Multiple *.nectar.txt files found in directory: " + directory,
+                         candidates );
+    }
+    return string("");
+}
+
+bool file_cache::find_project_file( const string &path, config_base &config )
+{
+    debug(debug::files) << "nectar::find_project_file::Called for " << path << ".\n";
+
+    if( lib::file_exists(path) )
+    {
+        debug(debug::files) << "nectar::find_project_file::Detected file.\n";
+        // TODO: generalize the directory seperators list
+        // TODO: seperate filename from (relative) path
+        const string::size_type index = path.find_last_of( "/\\" );
+        config.set_project_file( path.substr(index+1, string::npos) );
+        config.set_source_directory( path.substr(0, index) );
+    }
+    else if( lib::directory_exists(path) )
+    {
+        debug(debug::files) << "nectar::find_project_file detected directory.\n";
+        const string project_file = find_nectar_file( path, config );
+        // if the directory contains a *.nectar.txt file, set source directory as well
+        if( !project_file.empty() )
+        {
+            debug(debug::files) << "nectar::Project file found: " << project_file << ".\n";
+            config.set_source_directory( path );
+            config.set_project_file( project_file );
+            return true;
+        }
+    }
+    // return failure if some condition failed
+    debug(debug::files) << "nectar::No *.nectar.txt file found in " << path << ".\n";
+    return false;
+}
+
+const file_set & file_cache::get_source_file_set( const std::string &directory )
+{
+    debug(debug::files) << "file_set::get_source_file_set::Finding directory listing for "
+                        << directory << ".\n";
+    const auto result = m_source_files.find( directory );
+    if( result != m_source_files.end() )
+        return m_source_files[directory];
+    else
+    {
+        debug(debug::files) << "file_cache::get_source_file_set::Directory not found, scanning now.\n";
+        add_source_directory( directory );
+        return m_source_files[directory];
+    }
+}
+
+const file_set file_cache::find_source_file( const string &filename, const config_base &configuration,
+                                             const string_set &directories )
+{
+    debug(debug::files) << "file_cache::find_source_file::Called.\n";
+    const string &source_directory = configuration.source_directory();
+    // handle filename with directory prepended
+    const string_pair directory_filename( split_preceding_directory(filename) );
+    const string &preceding_directory = directory_filename.first;
+    const string &true_filename = directory_filename.second;
+    // handle empty "directories" case
+    string_set directories_to_search;
+    if( directories.empty() )
+        directories_to_search = { "" };
+    else
+    {
+        std::for_each( directories.begin(), directories.end(),
+                       [&](const string & directory)
+                       {
+                           const string full_dir = full_directory_name( source_directory,
+                                                                        full_directory_name(directory, preceding_directory) );
+                           if( directory_exists(full_dir))
+                           {
+                               debug(debug::files) << "file_cache::find_source_file::Adding deduced directory to search list: "
+                                                   << full_dir << "\n";
+                               directories_to_search.insert( full_dir );
+                           }
+                           else
+                               debug(debug::files) << "file_cache::find_source_file::Not adding non-existing deduced directory to search list: "
+                                                   << full_dir << ".\n";
+                       } );
+        if( directories_to_search.empty() )
+            directories_to_search = { "" };
+    }
+    debug(debug::files) << "file_cache::find_source_file::Looking for " << filename
+                        << " in the following subdirectories of " << source_directory
+                        << ":\n" << directories_to_search;
+
+    file_set result;
+
+    const auto end = directories_to_search.end();
+    for( auto it = directories_to_search.begin(); it != end; ++it )
+    {
+        const string &directory = full_directory_name( source_directory, *it );
+
+        debug(debug::files) << "file_cache::find_source_file::Loading directory contents for: "
+                            << directory << ".\n";
+        const file_set &files_on_disk = get_source_file_set( directory );
+        if( error_status() )
+            return result;
+
+        const auto end = files_on_disk.end();
+        for( auto it = files_on_disk.begin(); it != end; ++it )
+        {
+            const file &entry = *it;
+            debug(debug::files) << "file_cache::find_source_file::Matching " << entry.first
+                                << " vs " << true_filename << ".\n";
+            if( wildcard_compare(true_filename, entry.first) )
+            {
+                debug(debug::files) << "file_cache::find_source_file::Match found: " << entry.first << "\n";
+                result.insert( {directory + "/" + entry.first, entry.second} );
+            }
+        }
+    }
+    debug(debug::files) << "file_cache::find_source_file::Found " << result.size() << " match(es).\n";
+    return result;
+}
+const file_set file_cache::match_source_files( const string &filename, const config_base &configuration,
+                                               const string_set &directories )
+{
+    debug(debug::files) << "file_cache::match_source_files::Matching " << filename
+                        << " to all files in the source directories.\n";
+    file_set result;
+    const string_pair directory_filename( split_preceding_directory(filename) );
+    const string &preceding_directory( directory_filename.first );
+    const string &true_filename( directory_filename.second );
+
+    // search all directories, appended with preceding_directory
+    const auto directory_end = directories.end();
+    for( auto directory_it = directories.begin(); directory_it != directory_end; ++directory_it )
+    {
+        const string directory( full_directory_name(configuration.source_directory(),
+                                                    *directory_it + preceding_directory) );
+        if( !directory_exists(directory) )
+        {
+            debug(debug::files) << "file_cache::match_source_files::Skipping nonexistent directory: " << directory << ".\n";
+        }
+        debug(debug::files) << "file_cache::match_source_files::Looking in " << directory << " for matches.\n";
+
+
+        const file_set &files_on_disk = get_source_file_set( directory );
+        if( error_status() )
+            return result;
+
+        debug(debug::files) << "file_cache::match_source_files::Searching for match with " << files_on_disk.size() << " files.\n";
+
+        // match all files that were scanned from disk to the wildcard filename
+        const auto files_end = files_on_disk.end();
+        for( auto files_it = files_on_disk.begin(); files_it != files_end; ++files_it )
+        {
+            const file &entry = *files_it; // filename and last modified time
+            debug(debug::files) << "file_cache::match_source_files::Matching " << entry.first
+                                << " with " << true_filename << ".\n";
+            if( wildcard_compare(true_filename, entry.first) )
+            {
+                debug(debug::files) << "file_cache::match_source_files::Matched " << true_filename
+                                    << " to " << directory << "/" << entry.first << ".\n";
+                result.insert( { directory + "/" + entry.first, entry.second } );
+            }
+        }
+    }
+    debug(debug::files) << "file_cache::match_source_files::Found " << result.size() << " matches.\n";
+    return result;
+}
+
+void file_cache::add_source_directory( const std::string &directory )
+{
+#ifdef AMBROSIA_DEBUG
+    if( !directory_exists(directory) )
+        throw logic_error( "Directory does not exist: " + directory );
+#endif
+
+    debug(debug::files) << "file_cache::add_source_directory::Scanning files in source directory: " << directory << ".\n";
+    const auto result = m_source_files.insert( {directory, file_set()} );
+    if( !result.second )
+        debug(debug::files) << "file_cache::add_source_directory::Directory already present, and scanned.\n";
+    else
+    {
+        file_set &new_files = (*result.first).second;
+        scan_directory( std::inserter(new_files, new_files.begin()), directory );
+        debug(debug::files) << "file_cache::add_source_directory::Directory scanned.\n";
+    }
+}
+void file_cache::add_build_directory( const std::string &directory )
+{
+    if( !directory_exists(directory) )
+        // TODO: Create directory so scan_directory works OK. Check if creation was possible.
+        debug(debug::files) << "file_cache::add_build_direcctory::Creating build directory: " << directory << ".\n";
+
+    debug(debug::files) << "file_cache::add_build_directory::Scanning files in build directory: " << directory << ".\n";
+    const auto result = m_build_files.insert( {directory, file_set()} );
+    if( !result.second )
+        debug(debug::files) << "file_cache::add_source_directory::Directory already present, and scanned.\n";
+    else
+    {
+        file_set &new_files = (*result.first).second;
+        scan_directory( std::inserter(new_files, new_files.begin()), directory );
+    }
+}
+
+libambrosia_namespace_end

libAmbrosia/Source/Ambrosia/file_store.cpp

-/**
-  * Ambrosia/file_store.cpp
-  * Class implementation.
-  *
-  * Author: Ruben Van Boxem
-  *
-  **/
-
-// Class include
-#include "Ambrosia/file_store.h"
-
-// libAmbrosia includes
-#include "Ambrosia/algorithm.h"
-#include "Ambrosia/Configuration/ambrosia_config.h"
-#include "Ambrosia/debug.h"
-#include "Ambrosia/platform.h"
-#include "Ambrosia/status.h"
-
-// C++ includes
-#include <stdexcept>
-    using std::logic_error;
-/* <string> */
-    using std::string;
-/* <utility> */
-    using std::pair;
-
-libambrosia_namespace_begin
-
-file_store s_file_store; // declared in global.h
-
-file_store::file_store()
-:   m_source_files(),
-    m_build_files()
-{   }
-
-const file_set & file_store::get_source_file_set( const std::string &directory )
-{
-    debug(debug::files) << "file_set::get_source_file_set::Finding directory listing for "
-                        << directory << ".\n";
-    const auto result = m_source_files.find( directory );
-    if( result != m_source_files.end() )
-        return m_source_files[directory];
-    else
-    {
-        debug(debug::files) << "file_store::get_source_file_set::Directory not found, scanning now.\n";
-        add_source_directory( directory );
-        return m_source_files[directory];
-    }
-}
-
-const file_set file_store::find_source_file( const string &filename, const config_base &configuration,
-                                             const string_set &directories )
-{
-    debug(debug::files) << "file_store::find_source_file::Called.\n";
-    const string &source_directory = configuration.source_directory();
-    // handle filename with directory prepended
-    const string_pair directory_filename( split_preceding_directory(filename) );
-    const string &preceding_directory = directory_filename.first;
-    const string &true_filename = directory_filename.second;
-    // handle empty "directories" case
-    string_set directories_to_search;
-    if( directories.empty() )
-        directories_to_search = { "" };
-    else
-    {
-        std::for_each( directories.begin(), directories.end(),
-                       [&](const string & directory)
-                       {
-                           const string full_dir = full_directory_name( source_directory,
-                                                                        full_directory_name(directory, preceding_directory) );
-                           if( directory_exists(full_dir))
-                           {
-                               debug(debug::files) << "file_store::find_source_file::Adding deduced directory to search list: "
-                                                   << full_dir << "\n";
-                               directories_to_search.insert( full_dir );
-                           }
-                           else
-                               debug(debug::files) << "file_store::find_source_file::Not adding non-existing deduced directory to search list: "
-                                                   << full_dir << ".\n";
-                       } );
-        if( directories_to_search.empty() )
-            directories_to_search = { "" };
-    }
-    debug(debug::files) << "file_store::find_source_file::Looking for " << filename
-                        << " in the following subdirectories of " << source_directory
-                        << ":\n" << directories_to_search;
-
-    file_set result;
-
-    const auto end = directories_to_search.end();
-    for( auto it = directories_to_search.begin(); it != end; ++it )
-    {
-        const string &directory = full_directory_name( source_directory, *it );
-
-        debug(debug::files) << "file_store::find_source_file::Loading directory contents for: "
-                            << directory << ".\n";
-        const file_set &files_on_disk = get_source_file_set( directory );
-        if( error_status() )
-            return result;
-
-        const auto end = files_on_disk.end();
-        for( auto it = files_on_disk.begin(); it != end; ++it )
-        {
-            const file &entry = *it;
-            debug(debug::files) << "file_store::find_source_file::Matching " << entry.first
-                                << " vs " << true_filename << ".\n";
-            if( wildcard_compare(true_filename, entry.first) )
-            {
-                debug(debug::files) << "file_store::find_source_file::Match found: " << entry.first << "\n";
-                result.insert( {directory + "/" + entry.first, entry.second} );
-            }
-        }
-    }
-    debug(debug::files) << "file_store::find_source_file::Found " << result.size() << " match(es).\n";
-    return result;
-}
-const file_set file_store::match_source_files( const string &filename, const config_base &configuration,
-                                               const string_set &directories )
-{
-    debug(debug::files) << "file_store::match_source_files::Matching " << filename
-                        << " to all files in the source directories.\n";
-    file_set result;
-    const string_pair directory_filename( split_preceding_directory(filename) );
-    const string &preceding_directory( directory_filename.first );
-    const string &true_filename( directory_filename.second );
-
-    // search all directories, appended with preceding_directory
-    const auto directory_end = directories.end();
-    for( auto directory_it = directories.begin(); directory_it != directory_end; ++directory_it )
-    {
-        const string directory( full_directory_name(configuration.source_directory(),
-                                                    *directory_it + preceding_directory) );
-        if( !directory_exists(directory) )
-        {
-            debug(debug::files) << "file_store::match_source_files::Skipping nonexistent directory: " << directory << ".\n";
-        }
-        debug(debug::files) << "file_store::match_source_files::Looking in " << directory << " for matches.\n";
-
-
-        const file_set &files_on_disk = get_source_file_set( directory );
-        if( error_status() )
-            return result;
-
-        debug(debug::files) << "file_store::match_source_files::Searching for match with " << files_on_disk.size() << " files.\n";
-
-        // match all files that were scanned from disk to the wildcard filename
-        const auto files_end = files_on_disk.end();
-        for( auto files_it = files_on_disk.begin(); files_it != files_end; ++files_it )
-        {
-            const file &entry = *files_it; // filename and last modified time
-            debug(debug::files) << "file_store::match_source_files::Matching " << entry.first
-                                << " with " << true_filename << ".\n";
-            if( wildcard_compare(true_filename, entry.first) )
-            {
-                debug(debug::files) << "file_store::match_source_files::Matched " << true_filename
-                                    << " to " << directory << "/" << entry.first << ".\n";
-                result.insert( { directory + "/" + entry.first, entry.second } );
-            }
-        }
-    }
-    debug(debug::files) << "file_store::match_source_files::Found " << result.size() << " matches.\n";
-    return result;
-}
-
-void file_store::add_source_directory( const std::string &directory )
-{
-#ifdef AMBROSIA_DEBUG
-    if( !directory_exists(directory) )
-        throw logic_error( "Directory does not exist: " + directory );
-#endif
-
-    debug(debug::files) << "file_store::add_source_directory::Scanning files in source directory: " << directory << ".\n";
-    const auto result = m_source_files.insert( {directory, file_set()} );
-    if( !result.second )
-        debug(debug::files) << "file_store::add_source_directory::Directory already present, and scanned.\n";
-    else
-    {
-        file_set &new_files = (*result.first).second;
-        scan_directory( std::inserter(new_files, new_files.begin()), directory );
-        debug(debug::files) << "file_store::add_source_directory::Directory scanned.\n";
-    }
-}
-void file_store::add_build_directory( const std::string &directory )
-{
-    if( !directory_exists(directory) )
-        // TODO: Create directory so scan_directory works OK. Check if creation was possible.
-        debug(debug::files) << "file_store::add_build_direcctory::Creating build directory: " << directory << ".\n";
-
-    debug(debug::files) << "file_store::add_build_directory::Scanning files in build directory: " << directory << ".\n";
-    const auto result = m_build_files.insert( {directory, file_set()} );
-    if( !result.second )
-        debug(debug::files) << "file_store::add_source_directory::Directory already present, and scanned.\n";
-    else
-    {
-        file_set &new_files = (*result.first).second;
-        scan_directory( std::inserter(new_files, new_files.begin()), directory );
-    }
-}
-
-libambrosia_namespace_end

libAmbrosia/Source/Ambrosia/nectar.cpp

 #include "Ambrosia/algorithm.h"
 #include "Ambrosia/Configuration/ambrosia_config.h"
 #include "Ambrosia/debug.h"
-#include "Ambrosia/file_store.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/platform.h"
 #include "Ambrosia/status.h"
 #include "Ambrosia/target.h"
 
 libambrosia_namespace_begin
 
-const string find_nectar_file( const string &directory )
-{
-    debug(debug::files) << "nectar::find_nectar_file called for: " << directory << ".\n";
-    s_ambrosia_config.set_source_directory( directory );
-    file_set candidates = s_file_store.find_source_file( "*.nectar.txt", s_ambrosia_config );
-    switch( candidates.size() )
-    {
-        case 0:
-            emit_error( "No *.nectar.txt file found in " + directory );
-            break;
-        case 1:
-            return (*candidates.begin()).first; // first = filename, second = modified
-        default:
-            emit_error( "Multiple *.nectar.txt files found in directory: " + directory );
-            std::for_each( candidates.begin(), candidates.end(),
-                       [&candidates](const file &item)
-                       {
-                           emit_error( "\t" + item.first );
-                       } );
-    }
-    return string("");
-}
-
-bool find_project_file( const string &path, ambrosia_config &config )
-{
-    debug(debug::files) << "nectar::find_project_file::Called for " << path << ".\n";
-
-    if( lib::file_exists(path) )
-    {
-        debug(debug::files) << "nectar::find_project_file::Detected file.\n";
-        // TODO: generalize the directory seperators list
-        // seperate filename from (realtive) path
-        const string::size_type index = path.find_last_of( "/\\" );
-        config.set_project_file( path.substr(index+1, string::npos) );
-        config.set_source_directory( path.substr(0, index) );
-        return true;
-    }
-    else if( lib::directory_exists(path) )
-    {
-        debug(debug::files) << "nectar::find_project_file detected directory.\n";
-        const string project_file = lib::find_nectar_file( path );
-        // if the directory contains a *.nectar.txt file, set source directory as well
-        if( !project_file.empty() )
-        {
-            debug(debug::files) << "nectar::Project file found: " << project_file << ".\n";
-            config.set_source_directory( path );
-            config.set_project_file( project_file );
-            return true;
-        }
-    }
-    // return failure if some condition failed
-    debug(debug::files) << "nectar::No *.nectar.txt file found in " << path << ".\n";
-    return false;
-}
-
 void drink_nectar( const std::string &filename, target_list &targets )
 {
     // open file

libAmbrosia/Source/Ambrosia/project.cpp

   *
   **/
 
+// Class include
 #include "Ambrosia/project.h"
 
+// libAmbrosia includes
+#include "Ambrosia/algorithm.h"
+#include "Ambrosia/debug.h"
+
+// C++ includes
+/* <string> */
+    using std::string;
+
 libambrosia_namespace_begin
 
-ambrosia_config project::m_configuration = ambrosia_config();
-file_store project::m_file_store = file_store();
+ambrosia_config project::configuration = ambrosia_config();
 
-project::project()
-:   m_subprojects()
+project::project( file_cache &file_cache)
+:   m_file_cache(file_cache),
+    m_subprojects()
 {   }
 
-// Getters
-const ambrosia_config & project::config() const
+// Static functions
+void project::set_internal_option( const string &option, const string &value )
 {
-    return m_configuration;
-}
-ambrosia_config & project::config()
-{
-    return m_configuration;
+    debug(debug::commandline) << "commandline::set_internal_option::Ambrosia internal option: " << option
+                              << " with value " << value << " being set.\n";
+
+    if( "cross" == option )
+    {
+        debug(debug::commandline) << "commandline::set_internal_option::Cross-compiling for "
+                                  << value << ".\n";
+        lib::project::configuration.set_ambrosia_cross( value );
+    }
+    #ifdef AMBROSIA_DEBUG
+    else if( "d" == option || "debug" == option )
+    {
+        const uint32_t level = lib::from_string<uint32_t>( value );
+        // check validity, partial check on input as well
+        if( level > lib::s_max_debug_level )//|| level < 0 )
+            lib::emit_error( "Debug level must be a number between 0 and 9." );
+        debug(debug::always) << "begin::Setting debug level to " << level << ".\n";
+        debug::s_level = static_cast<debug::type>(level);
+    }
+    #endif // AMBROSIA_DEBUG
+    else if( "gnu-prefix" == option )
+    {
+        debug(debug::commandline) << "commandline::set_internal_option::Cross-compiling with GNU prefix "
+                                  << value << ".\n";
+        lib::project::configuration.set_gnu_prefix( value );
+    }
+    else
+        lib::emit_error( "Unknown option passed to Ambrosia: \n\t-" + option + "=" + value );
 }
 
 // Setters

libAmbrosia/Source/Ambrosia/target.cpp

 #include "Ambrosia/Configuration/ambrosia_config.h"
 #include "Ambrosia/debug.h"
 #include "Ambrosia/enum_maps.h"
-#include "Ambrosia/file_store.h"
+#include "Ambrosia/file_cache.h"
 #include "Ambrosia/platform.h"
 #include "Ambrosia/status.h"
 
 {
     if( contains(filename, "*?") )
     {
-        const file_set matches = s_file_store.match_source_files( filename, m_build_config,
+        const file_set matches = s_file_cache.match_source_files( filename, m_build_config,
                                                                   m_source_directories[type] );
         if( matches.empty() )
             return emit_nectar_error( "No files matching " + filename + " found.",
     }
     else
     {
-        const file_set matches = s_file_store.find_source_file( filename, m_build_config,
+        const file_set matches = s_file_cache.find_source_file( filename, m_build_config,
                                                                 m_source_directories[type] );
         switch( matches.size() )
         {
 }
 void target::remove_file( const file_type type, const string &filename )
 {
-    s_file_store.match_source_files( filename, m_build_config,
+    s_file_cache.match_source_files( filename, m_build_config,
                                      m_source_directories[type] );
     emit_error( "target::remove_file::Unimplementented." );
 }
     if( !directory_exists(full_subdirectory_name) )
         return false;
 
-    s_file_store.add_source_directory( full_subdirectory_name );
+    s_file_cache.add_source_directory( full_subdirectory_name );
     m_source_directories[type].insert( directory );
     return true;
 }

libAmbrosia/libAmbrosia.pro

     Include/Ambrosia/target.h \
     Include/Ambrosia/algorithm.h \
     Include/Ambrosia/node.h \
-    Include/Ambrosia/file_store.h \
     Include/Ambrosia/nectar_loader.h \
     Include/Ambrosia/Configuration/ambrosia_config.h \
     Include/Ambrosia/Configuration/build_config.h \
     Include/Ambrosia/project.h \
     Include/Ambrosia/Error/syntax_error.h \
     Include/Ambrosia/Error/error.h \
-    Include/Ambrosia/Error/nectar_error.h
+    Include/Ambrosia/Error/nectar_error.h \
+    Include/Ambrosia/file_cache.h \
+    Include/Ambrosia/Error/soft_error.h \
+    Include/Ambrosia/Error/commandline_error.h
 
 SOURCES += \
     Source/Ambrosia/Platform/common.cpp \
     Source/Ambrosia/algorithm.cpp \
     Source/Ambrosia/debug.cpp \
     Source/Ambrosia/node.cpp \
-    Source/Ambrosia/file_store.cpp \
     Source/Ambrosia/nectar_loader.cpp \
     Source/Ambrosia/Configuration/ambrosia_config.cpp \
     Source/Ambrosia/Configuration/build_config.cpp \
     Source/Ambrosia/project.cpp \
     Source/Ambrosia/Error/syntax_error.cpp \
     Source/Ambrosia/Error/error.cpp \
-    Source/Ambrosia/Error/nectar_error.cpp
+    Source/Ambrosia/Error/nectar_error.cpp \
+    Source/Ambrosia/file_cache.cpp \
+    Source/Ambrosia/Error/soft_error.cpp \
+    Source/Ambrosia/Error/commandline_error.cpp
 
 *win32*:SOURCES += Source/Ambrosia/Platform/windows.cpp
 *linux*:SOURCES += Source/Ambrosia/Platform/unix.cpp
 
 
 
+
+
+
+
+
+
+
+