diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e812a7cb4c03a6cb43d45b66689b17c6379149b..5452eeeec3fbe38b94ff18b364624e162c6317cd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,6 @@ target_include_directories(CTUApex PUBLIC
         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>)
 
 target_link_libraries(CTUApex metacg)
-target_link_libraries(CTUApex minicpr)
+#target_link_libraries(CTUApex minicpr)
 target_link_libraries(CTUApex clangTooling)
 target_compile_options(CTUApex PUBLIC -fno-rtti)
\ No newline at end of file
diff --git a/include/ExtractionMetadata.h b/include/ExtractionMetadata.h
index ad733425316c25fe8bd765b65598c3a2a7143fa4..8a63634b28a537867b316cdc5e7823e50e3afd26 100644
--- a/include/ExtractionMetadata.h
+++ b/include/ExtractionMetadata.h
@@ -5,7 +5,7 @@
 #ifndef CTUAPEX_EXTRACTIONMETADATA_H
 #define CTUAPEX_EXTRACTIONMETADATA_H
 
-#include <MetaData.h>
+#include <metadata/MetaData.h>
 
 class ExtractionMetadata : public metacg::MetaData::Registrar<ExtractionMetadata> {
 public:
diff --git a/src/CTUApexConsumer.cpp b/src/CTUApexConsumer.cpp
index 6c979368cb07b5db4525943b9aec5c19719972c5..8da27a9630632d787c19df31c6bce02737f736da 100644
--- a/src/CTUApexConsumer.cpp
+++ b/src/CTUApexConsumer.cpp
@@ -147,10 +147,14 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
         outFile << getNextExtractionBlock().contents << "\n";
     }
 
-    outFile.close();
     SPDLOG_INFO("Generate wrapper calls");
     SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED");
 
+    if(auto md=call_graph->getMain()->checkAndGet<ExtractionMetadata>(); md.first && !md.second->isMarkedToExtract()){
+        //we have no main function and need to create or own
+        outFile<<"\nint main(){return 0;}\n";
+    }
+
     // Outline the code we want
     //SPDLOG_DEBUG("Generating outline");
     //assert(output.empty());
@@ -164,6 +168,8 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
     //    output = extracted_source;
     //}
 
+    outFile.close();
+
     SPDLOG_INFO("Clean CG for next run");
     for (const auto &node: call_graph->getNodes()) {
         if (node.second->has<ExtractionMetadata>()) {
diff --git a/src/main.cpp b/src/main.cpp
index 9c40d69553d250867ccfc1060eea2a5b207a69da..cef1d5d257d2d010b88ab87da97e009280985537 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,97 +13,12 @@
 #include "CTUApexAction.h"
 #include "CTUApexConsumer.h"
 
-#include "MCGReader.h"
-#include "MCGWriter.h"
+#include "io/VersionTwoMCGReader.h"
+#include "io/VersionThreeMCGReader.h"
 
 #include "Util.h"
 #include "ExtractionMetadata.h"
 
-class FilePropertiesMetaData : public metacg::MetaData::Registrar<FilePropertiesMetaData> {
-public:
-    static constexpr const char *key = "fileProperties";
-
-    FilePropertiesMetaData() : origin("INVALID"), fromSystemInclude(false), lineNumber(0) {}
-
-    explicit FilePropertiesMetaData(const nlohmann::json &j) {
-        if (j.is_null()) {
-            metacg::MCGLogger::instance().getConsole()->trace("Could not retrieve meta data for {}", key);
-            return;
-        }
-
-        std::string fileOrigin = j["origin"].get<std::string>();
-        bool isFromSystemInclude = j["systemInclude"].get<bool>();
-        origin = fileOrigin;
-        fromSystemInclude = isFromSystemInclude;
-    }
-
-    nlohmann::json to_json() const final {
-        nlohmann::json j;
-        j["origin"] = origin;
-        j["systemInclude"] = fromSystemInclude;
-        return j;
-    };
-
-    virtual const char *getKey() const final { return key; }
-
-    std::string origin;
-    bool fromSystemInclude;
-    int lineNumber;
-};
-
-class PiraOneData : public metacg::MetaData::Registrar<PiraOneData> {
-public:
-    static constexpr const char *key = "numStatements";
-
-    PiraOneData() = default;
-
-    explicit PiraOneData(const nlohmann::json &j) {
-        metacg::MCGLogger::instance().getConsole()->trace("Running PiraOneMetaDataRetriever::read from json");
-        if (j.is_null()) {
-            metacg::MCGLogger::instance().getConsole()->trace("Could not retrieve meta data for {}", key);
-            return;
-        }
-        auto jsonNumStmts = j.get<long long int>();
-        metacg::MCGLogger::instance().getConsole()->debug("Read {} stmts from file", jsonNumStmts);
-        setNumberOfStatements(jsonNumStmts);
-    }
-
-    nlohmann::json to_json() const final {
-        nlohmann::json j;
-        j["numStatements"] = getNumberOfStatements();
-        return j;
-    };
-
-    virtual const char *getKey() const final { return key; }
-
-    void setNumberOfStatements(int numStmts) { this->numStmts = numStmts; }
-
-    int getNumberOfStatements() const { return this->numStmts; }
-
-    void setHasBody(bool hasBody = true) { this->hasBody = hasBody; }
-
-    bool getHasBody() const { return this->hasBody; }
-
-    void setDominantRuntime(bool dominantRuntime = true) { this->dominantRuntime = dominantRuntime; }
-
-    bool isDominantRuntime() const { return this->dominantRuntime; }
-
-    void setComesFromCube(bool fromCube = true) { this->wasInPreviousProfile = fromCube; }
-
-    bool comesFromCube() const { return this->wasInPreviousProfile; }
-
-    bool inPreviousProfile() const { return wasInPreviousProfile; }
-
-private:
-    bool wasInPreviousProfile{false};
-    bool dominantRuntime{false};
-    bool hasBody{false};
-    int numStmts{0};
-};
-
-inline void to_json(nlohmann::json &j, const PiraOneData &data) {
-    j = nlohmann::json{{"numStatements", data.getNumberOfStatements()}};
-}
 
 //Das sind convenience definitionen, dass wir nicht so viel tippen müssen
 using namespace llvm;
@@ -120,6 +35,16 @@ static cl::opt<std::string> cg_file("cg-file", cl::desc("MetaCG file containing
 enum class LogLevel {
     Trace, Debug, Info, Warning, Error, /* Critical,*/ Off
 };
+
+//static cl::opt<std::string> extractionStart("extract",
+//                                            cl::desc("Qualified name of the function to start the extraction from"),
+//                                            cl::value_desc("functionname"), cl::Optional, cl::cat(CTUApex));
+
+static cl::list<std::string> extractionPoints("extract",
+                                              cl::desc("Qualified names of the function to start the extraction from"),
+                                              cl::value_desc("Comma separated list of function names"), cl::Optional,
+                                              cl::cat(CTUApex));
+
 static cl::opt<LogLevel> LoggingLevel("log-level", cl::desc("Select log level"),
                                       cl::values(clEnumValN(LogLevel::Trace, "trace", "Enable Trace and higher logs"),
                                                  clEnumValN(LogLevel::Debug, "debug", "Enable Debug and higher logs"),
@@ -129,31 +54,31 @@ static cl::opt<LogLevel> LoggingLevel("log-level", cl::desc("Select log level"),
                                                  clEnumValN(LogLevel::Error, "error", "Enable only Error logs"),
                                                  clEnumValN(LogLevel::Off, "off", "Disable all logging")),
                                       cl::init(LogLevel::Info), cl::cat(CTUApex));
+
 static cl::opt<bool> OnlyWrapper("generate-only-wrapper", cl::desc("Output only the wrapper function"),
                                  cl::cat(CTUApex));
 static cl::opt<bool> DumpAnalysisResult("dump-analysis-result",
                                         cl::desc("Dump the dependence analysis result to stdout"), cl::cat(CTUApex));
 
+class CTUApexFactory : clang::ASTFrontendAction {
+public:
+    CTUApexFactory(metacg::Callgraph &cg) : cg(&cg) {}
 
-template<typename T, class... Args>
-std::unique_ptr<clang::tooling::FrontendActionFactory> argumentParsingFrontendActionFactory(Args... args) {
-
-    class SimpleFrontendActionFactory : public clang::tooling::FrontendActionFactory {
-    public:
-        explicit SimpleFrontendActionFactory(Args... constructorArgs) {
-            fn1 = [=]() { return std::make_unique<T>(constructorArgs...); };
-        }
-
-        std::unique_ptr<clang::FrontendAction> create() override {
-            return fn1();
-        }
+    std::unique_ptr<clang::ASTConsumer> newASTConsumer() {
+        return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas));
+    }
 
-    private:
-        std::function<std::unique_ptr<T>()> fn1; // function
-    };
+    std::unique_ptr<clang::ASTConsumer> CreateASTConsumer([[maybe_unused]] clang::CompilerInstance &compiler,
+                                                          [[maybe_unused]] llvm::StringRef sr) {
+        return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas));
+    }
 
-    return std::unique_ptr<FrontendActionFactory>(new SimpleFrontendActionFactory(args...));
-}
+private:
+    std::vector<ExtractionBlock> includes;
+    std::vector<ExtractionBlock> macros;
+    std::vector<ExtractionBlock> pragmas;
+    metacg::Callgraph *cg;
+};
 
 
 void markCalleesToExtract(const size_t nodeID, const metacg::Callgraph &cg) {
@@ -162,6 +87,7 @@ void markCalleesToExtract(const size_t nodeID, const metacg::Callgraph &cg) {
         markCalleesToExtract(call->getId(), cg);
     }
 }
+
 void markFunctionsAlongCallpaths(metacg::Callgraph &cg) {
     SPDLOG_INFO("Compute set of functions to be extracted");
     for (const auto &node: cg.getNodes()) {
@@ -204,18 +130,40 @@ int main(int argc, const char **argv) {
     }
 
     CommonOptionsParser &OptionsParser = ExpectedParser.get();
-    ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
-    std::string error = "error";
-    auto fcd = FixedCompilationDatabase::loadFromDirectory("", error);
+
+    ClangTool tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
+
     metacg::io::FileSource fs(cg_file.getValue());
-    metacg::io::VersionTwoMetaCGReader mcgReader(fs);
+
+    std::unique_ptr<metacg::io::MetaCGReader> mcgReader;
+
+    if (fs.get().at("_MetaCG").at("version") == "3.0") {
+        mcgReader = std::make_unique<metacg::io::VersionThreeMetaCGReader>(fs);
+    } else if (fs.get().at("_MetaCG").at("version") == "2.0") {
+        mcgReader = std::make_unique<metacg::io::VersionTwoMetaCGReader>(fs);
+    } else {
+        assert(false && "File corrupt or format not specified");
+    }
+
     auto &mcgManager = metacg::graph::MCGManager::get();
     mcgManager.addToManagedGraphs("emptyGraph", std::make_unique<metacg::Callgraph>());
-    mcgReader.read(mcgManager);
+    mcgReader->read(mcgManager);
+    auto &cg = *mcgManager.getCallgraph();
+    //Add extraction point gotten via the CLI
+    for(const auto& extractionFunc : extractionPoints){
+        if (cg.hasNode(extractionFunc)) {
+            auto *md = new ExtractionMetadata();
+            md->setMarkedToExtract(true);
+            cg.getNode(extractionFunc)->addMetaData(md);
+        }else{
+            SPDLOG_ERROR("The given function: "+ extractionFunc + " does not exist in the given callgraph");
+        }
+    }
 
-    markFunctionsAlongCallpaths(*mcgManager.getCallgraph());
+    markFunctionsAlongCallpaths(cg);
 
-    Tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get());
+    tool.run(clang::tooling::newFrontendActionFactory<CTUApexFactory>(
+            new CTUApexFactory(*mcgManager.getCallgraph())).get());
     return 0;
 }