Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) QtCreatorProFile

 

STLQt CreatorLubuntu

 

QtCreatorProFile is a Qt project file (.pro) class.

 

QtCreatorProFile is tested by the tool TestQtCreatorProFile.

Technical facts

 

 

 

 

 

 

./CppQtCreatorProFile/CppQtCreatorProFile.pri

 

INCLUDEPATH += \
    ../../Classes/CppQtCreatorProFile

SOURCES += \
    ../../Classes/CppQtCreatorProFile/qtcreatorprofile.cpp \
    ../../Classes/CppQtCreatorProFile/qtcreatorprofilezipscript.cpp

HEADERS  += \
    ../../Classes/CppQtCreatorProFile/qtcreatorprofile.h \
    ../../Classes/CppQtCreatorProFile/qtcreatorprofilezipscript.h

OTHER_FILES += \
    ../../Classes/CppQtCreatorProFile/Licence.txt

 

 

 

 

 

./CppQtCreatorProFile/qtcreatorprofile.h

 

//---------------------------------------------------------------------------
/*
QtCreatorProFile, class to parse Qt Project files
Copyright (C) 2010-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtCreatorProFile.htm
//---------------------------------------------------------------------------
#ifndef QTCREATORPROFILE_H
#define QTCREATORPROFILE_H

#include <iosfwd>
#include <set>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/checked_delete.hpp>
#include <boost/shared_ptr.hpp>
#include "about.h"
#pragma GCC diagnostic pop

namespace ribi {

///QtCreatorProFile parses .pro files
struct QtCreatorProFile
{
  ///Parse a .pro file, throws a std::logic_error if
  ///filename is not a regular file
  explicit QtCreatorProFile(const std::string& filename);
  QtCreatorProFile(const QtCreatorProFile&) = delete;
  QtCreatorProFile& operator=(const QtCreatorProFile&) = delete;

  ///Obtain this class its About information
  static ribi::About GetAbout() noexcept;

  ///Obtain the CONFIG
  const std::set<std::string>& GetConfig() const noexcept { return m_config; }

  ///Obtain the DEFINES
  const std::set<std::string>& GetDefines() const noexcept { return m_defines; }

  ///Obtain the FORMS
  const std::set<std::string>& GetForms() const noexcept { return m_forms; }

  ///Obtain the HEADERS
  const std::set<std::string>& GetHeaders() const noexcept { return m_headers; }

  ///Obtain the INCLUDEPATH
  const std::set<std::string>& GetIncludepath() const noexcept { return m_includepath; }

  ///Obtain the LIBS
  const std::set<std::string>& GetLibs() const noexcept { return m_libs; }

  ///Obtain the OTHER_FILES
  const std::set<std::string>& GetOtherFiles() const noexcept { return m_other_files; }

  ///Obtain the include(something.pri)
  const std::set<std::string>& GetPriFiles() const noexcept { return m_pri_files; }

  ///Get the project file its file name
  const std::string& GetQtCreatorProFilename() const noexcept { return m_pro_filename; }

  ///Obtain the QMAKE_CXXFLAGS
  const std::set<std::string>& GetQmakeCxxflags() const noexcept { return m_qmake_cxxflags; }

  ///Obtain the QT
  const std::set<std::string>& GetQt() const noexcept { return m_qt; }

  ///Obtain the RESOURCES
  const std::set<std::string>& GetResources() const noexcept { return m_resources; }

  ///Obtain the SOURCES
  const std::set<std::string>& GetSources() const noexcept { return m_sources; }

  ///Obtain the TARGET
  const std::set<std::string>& GetTarget() const noexcept { return m_target; }

  ///Obtain the TEMPLATE
  const std::set<std::string>& GetTemplate() const noexcept { return m_template; }

  ///Obtain this class its version
  static std::string GetVersion() noexcept;

  ///Obtain this class its version history
  static std::vector<std::string> GetVersionHistory() noexcept;

  ///Set the CONFIG
  void SetConfig(const std::set<std::string>& s) { m_config = s; }

  ///Set the DEFINES
  void SetDefines(const std::set<std::string>& s) { m_defines = s; }

  ///Set the FORMS
  void SetForms(const std::set<std::string>& s) { m_forms = s; }

  ///Set the HEADERS
  void SetHeaders(const std::set<std::string>& s) { m_headers = s; }

  ///Set the INCLUDEPATH
  void SetIncludepath(const std::set<std::string>& s) { m_includepath = s; }

  ///Set the LIBS
  void SetLibs(const std::set<std::string>& s) { m_libs = s; }

  ///Set the OTHER_FILES
  void SetOtherFiles(const std::set<std::string>& s) { m_other_files = s; }

  ///Set the include(something.pri) files
  void SetPriFiles(const std::set<std::string>& s) { m_pri_files = s; }

  ///Set the project file its file name
  void SetQtCreatorProFilename(const std::string& s) { m_pro_filename = s; }

  ///Set the QMAKE_CXXFLAGS
  void SetQmakeCxxflags(const std::set<std::string>& s) { m_qmake_cxxflags = s; }

  ///Set the QT
  void SetQt(const std::set<std::string>& s) { m_qt = s; }

  ///Set the RESOURCES
  void SetResources(const std::set<std::string>& s) { m_resources = s; }

  ///Set the SOURCES
  void SetSources(const std::set<std::string>& s)  { m_sources = s; }

  ///Set the TARGET
  void SetTarget(const std::set<std::string>& s) { m_target = s; }

  ///Set the TEMPLATE
  void SetTemplate(const std::set<std::string>& s) { m_template = s; }

  private:
  ///Be sure the class is correctly deleted
  ~QtCreatorProFile() noexcept {}
  friend void boost::checked_delete<>(QtCreatorProFile* x);

  ///The items at CONFIG
  std::set<std::string> m_config;

  ///The items at DEFINES
  std::set<std::string> m_defines;

  ///The items at FORMS
  std::set<std::string> m_forms;

  ///The items at HEADERS
  std::set<std::string> m_headers;

  ///The items at INCLUDEPATH
  std::set<std::string> m_includepath;

  ///The items at LIBS
  std::set<std::string> m_libs;

  ///The items at OTHER_FILES
  std::set<std::string> m_other_files;

  ///The include(something.pri) files
  std::set<std::string> m_pri_files;

  ///The .pro file to parse
  std::string m_pro_filename;

  ///The items at QMAKE_CXXFLAGS
  std::set<std::string> m_qmake_cxxflags;

  ///The items at QT
  std::set<std::string> m_qt;

  ///The items at RESOURCES
  std::set<std::string> m_resources;

  ///The item at TARGET
  std::set<std::string> m_target;

  ///The items at TEMPLATE
  std::set<std::string> m_template;

  ///The items at SOURCES
  std::set<std::string> m_sources;

  void DoReplacements(std::vector<std::string>& v);

  ///Parse the .pro file its content, split into lines
  void Parse(std::stringstream& data);

  void RemoveComments(std::vector<std::string>& v);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const QtCreatorProFile& p);
  friend bool operator==(const QtCreatorProFile& lhs, const QtCreatorProFile& rhs);

};

std::ostream& operator<<(std::ostream& os, const QtCreatorProFile& p);
bool operator==(const QtCreatorProFile& lhs, const QtCreatorProFile& rhs);

} //~namespace ribi

#endif // QTCREATORPROFILE_H

 

 

 

 

 

./CppQtCreatorProFile/qtcreatorprofile.cpp

 

//---------------------------------------------------------------------------
/*
QtCreatorProFile, class to parse Qt Project files
Copyright (C) 2010-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtCreatorProFile.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include "qtcreatorprofile.h"

#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iterator>
#include <map>
#include <sstream>
#include <string>
#include <vector>

#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/function.hpp>

#include "fileio.h"
#include "trace.h"
#include "testtimer.h"

#pragma GCC diagnostic pop

ribi::QtCreatorProFile::QtCreatorProFile(const std::string& filename)
  :
    m_config{},
    m_defines{},
    m_forms{},
    m_headers{},
    m_includepath{},
    m_libs{},
    m_other_files{},
    m_pri_files{},
    m_pro_filename{fileio::FileIo().ConvertPathToUnix(filename)},
    m_qmake_cxxflags{},
    m_qt{},
    m_resources{},
    m_target{},
    m_template{},
    m_sources{}
{
  #ifndef NDEBUG
  Test();
  #endif
  if (!ribi::fileio::FileIo().IsRegularFile(m_pro_filename))
  {
    std::stringstream s;
    s << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Filename '" << m_pro_filename << "' must be a regular file";
    throw std::logic_error(s.str().c_str());
  }
  assert(fileio::FileIo().IsUnixPath(m_pro_filename));
  if (!fileio::FileIo().IsUnixPath(m_pro_filename))
  {
    std::stringstream s;
    s << __FILE__ << "(" <<  (__LINE__) <<  ") : "
      << "Filename '" << m_pro_filename << "' must have a Linux-styl path "
      << " (this is, folders must be seperated by a slash, instead of a backslash)"
    ;
    throw std::logic_error(s.str().c_str());
  }



  std::vector<std::string> v{ribi::fileio::FileIo().FileToVector(m_pro_filename)};
  RemoveComments(v);
  DoReplacements(v);
  std::stringstream data;
  std::copy(std::begin(v),std::end(v),std::ostream_iterator<std::string>(data," "));
  Parse(data);
}

void ribi::QtCreatorProFile::DoReplacements(std::vector<std::string>& v)
{
  for (std::string& s: v)
  {
    boost::algorithm::replace_all(s,"include (","include(");
  }
}

ribi::About ribi::QtCreatorProFile::GetAbout() noexcept
{
  ribi::About a(
    "Richel Bilderbeek",
    "QtCreatorProFile",
    "class to parse Qt Project files",
    "the 19th of August 2013",
    "2010-2015",
    "http://www.richelbilderbeek.nl/CppQtCreatorProFile.htm",
    GetVersion(),
    GetVersionHistory());
  return a;
}

std::string ribi::QtCreatorProFile::GetVersion() noexcept
{
  return "3.0";
}

std::vector<std::string> ribi::QtCreatorProFile::GetVersionHistory() noexcept
{
  return {
    "2010-12-19: version 1.0: initial version",
    "2011-01-06: version 1.1: added GetCommonRoot and GetLibs member functions, added operator<<",
    "2011-09-11: version 1.2: fixed bug",
    "2012-02-25: version 1.3: added GetAbout member function",
    "2012-02-28: version 1.4: added support for INCLUDEPATH, FORMS, OTHER_FILES, RESOURCES and QMAKE_CXXFLAGS",
    "2012-05-30: version 1.5: added SimplifyPath",
    "2012-08-13: version 1.6: modifiers like win32 and unix are ignored, instead of yielding an error",
    "2012-12-23: version 1.7: set destructor to private, except for boost::checked_delete",
    "2012-12-23: version 1.8: renamed to QtCreatorProFile due to naming conflicts when cross-compiling",
    "2013-05-18: version 2.0: simplified architecture by removing file I/O",
    "2013-08-19: version 2.1: replaced Boost.Regex by Boost.Xpressive, removed Boost.Filesystem",
    "2014-01-27: version 2.2: removes all comments, can detect includes of .pri files",
    "2014-05-02: version 3.0: use UNIX path seperators only"
  };
}

void ribi::QtCreatorProFile::Parse(std::stringstream& data)
{
  const bool verbose{false};
  std::set<std::string> * p = nullptr; //A set to write to
  enum class Prefix { none, plus, minus };
  Prefix prefix = Prefix::none;
  while (data)
  {
    std::string s;
    data >> s;
    if (verbose) { TRACE(s); }
    assert(s[0] != '#' && "Comments are already removed");
    if (s[0] == '{') continue;
    if (s[0] == '}') continue;
    if (s[0] == '\\') continue;
    if (s.size() > 7 && s.substr(0,7) == "include")
    {
      std::string t = s.substr(8,s.size() - 8 - 1);
      if (verbose) { TRACE(t); }
      while (t[0] == ' ' || t[0] == '(') t = t.substr(1,t.size()-1);
      if (verbose) { TRACE(t); }
      while (t.back() == ' ' || t.back() == ')') t.pop_back();
      if (verbose) { TRACE(t); }
      assert(t.find('(') == std::string::npos);
      assert(t.find(')') == std::string::npos);
      m_pri_files.insert(t);
      continue;
    }
    const std::vector<std::string> conditional_sections {
      "unix", "win32", "static", "debug", "release"
    };
    if (std::count(conditional_sections.begin(),conditional_sections.end(),s))
    {
      p = nullptr;
      continue;
    }
    const std::map<std::string,std::set<std::string>* > m {
      { "CONFIG"        ,&m_config },
      { "DEFINES"       ,&m_defines },
      { "FORMS"         ,&m_forms },
      { "HEADERS"       ,&m_headers },
      { "INCLUDEPATH"   ,&m_includepath },
      { "LIBS"          ,&m_libs },
      { "OTHER_FILES"   ,&m_other_files },
      { "QMAKE_CXXFLAGS",&m_qmake_cxxflags },
      { "QT"            ,&m_qt },
      { "RESOURCES"     ,&m_resources },
      { "SOURCES"       ,&m_sources },
      { "TARGET"        ,&m_target },
      { "TEMPLATE"      ,&m_template }
    };
    const std::map<std::string,std::set<std::string>* >::const_iterator iter {
      std::find_if(std::begin(m),std::end(m),
        [s](const std::pair<std::string,std::set<std::string>* > sub_pair)
        {
          return sub_pair.first == s;
        }
      )
    };
    if (iter != std::end(m))
    {
      if (verbose) { const std::string msg = "Set pointer to " + iter->first; TRACE(msg); }
      p = iter->second;
      prefix = Prefix::none;
      continue;
    }
    //Determine prefixes
    bool has_prefixes = true;
    while (has_prefixes)
    {
      has_prefixes = false;
      if (!s.empty() && s[0] == '+')
      {
        prefix = Prefix::plus;
        s = s.substr(1,s.size() - 1);
        has_prefixes = true;
      }
      else if (!s.empty() && s[0] == '-')
      {
        prefix = Prefix::minus;
        s = s.substr(1,s.size() - 1);
        has_prefixes = true;
      }
      else if (!s.empty() && s[0] == '\\')
      {
        s = s.substr(1,s.size() - 1);
        has_prefixes = true;
      }
      else if (!s.empty() && s[0] == '=')
      {
        s = s.substr(1,s.size() - 1);
        has_prefixes = true;
      }
    }
    //Remove possible postfix
    if (!s.empty())
    {
      if (s[ s.size() - 1] == '\\') s.resize(s.size() - 1);

    }
    if (p && !s.empty())
    {
      if (verbose) { const std::string msg = "Added " + s; TRACE(msg); }
      p->insert(
        (prefix == Prefix::minus ? "-" : "") + s);
    }
  }
}

void ribi::QtCreatorProFile::RemoveComments(std::vector<std::string>& v)
{
  for (std::string& s: v)
  {
    const std::string t = boost::algorithm::trim_copy(s);
    if (t[0] == '#')
    {
      s = "";
      continue;
    }
    if (t.size() >= 7 && t.substr(0,7) == "message")
    {
      s = "";
      continue;
    }

    const auto iter = std::find(std::begin(t),std::end(t),'#');
    if (iter != std::end(t))
    {
      s.assign(std::begin(t),iter);
    }

    assert(std::find(std::begin(s),std::end(s),'#') == std::end(s)
      && "Every comment is removed");
  }

}

#ifndef NDEBUG
void ribi::QtCreatorProFile::Test() noexcept
{
  //Test exactly once
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  fileio::FileIo();

  const TestTimer test_timer(__func__,__FILE__,1.0);
  {
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f << "SOURCES += qtmain.cpp";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetSources().size() == 1);
    assert(p.GetSources().count("qtmain.cpp"));
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
  {
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f << "include(something.pri)";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetPriFiles().size() == 1);
    assert(p.GetPriFiles().count("something.pri"));
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
  {
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f << "include (something.pri)";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetPriFiles().size() == 1);
    assert(p.GetPriFiles().count("something.pri"));
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
  {
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f << "HEADERS += header.h #Must remove this comment";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetHeaders().size() == 1);
    assert(p.GetHeaders().count("header.h"));
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
  {
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f << "#-------------------------------------------------\n"
        << "#\n"
        << "# Project created by QtCreator 2010-12-19T16:24:53\n"
        << "#\n"
        << "#-------------------------------------------------\n"
        << "QT       += core\n"
        << "QT       -= gui\n"
        << "LIBS     += -lwt -lboost_regex\n"
        << "TARGET = ToolTestQtCreatorProFile\n"
        << "CONFIG   += console\n"
        << "CONFIG   -= app_bundle\n"
        << "TEMPLATE = app\n"
        << "SOURCES += main.cpp \\\n"
        << "    profile.cpp\n"
        << "HEADERS += \\\n"
        << "    profile.h";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetConfig().size() == 2);
    assert(p.GetConfig().count("console"));
    assert(p.GetConfig().count("-app_bundle"));
    assert(p.GetHeaders().size() == 1);
    assert(p.GetHeaders().count("profile.h"));
    assert(p.GetLibs().size() == 2);
    assert(p.GetLibs().count("-lwt"));
    assert(p.GetLibs().count("-lboost_regex"));
    assert(p.GetQtCreatorProFilename() == mypath);
    assert(p.GetQt().size() == 2);
    assert(p.GetQt().count("core"));
    assert(p.GetQt().count("-gui"));
    assert(p.GetSources().size() == 2);
    assert(p.GetSources().count("main.cpp"));
    assert(p.GetSources().count("profile.cpp"));
    assert(p.GetTarget().count("ToolTestQtCreatorProFile") == 1);
    assert(p.GetTemplate().size() == 1);
    assert(p.GetTemplate().count("app"));
    {
      std::stringstream ss;
      ss << p << '\n';
    }
    //TRACE("Test QtCreatorProFile::operator==");
    {
      QtCreatorProFile q(mypath);
      assert(p == q);
    }
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
  //TRACE("Test QtCreatorProFile::Merge");
  {
    const std::string mypath1 { fileio::FileIo().GetTempFileName() };
    const std::string mypath2 { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath1);
      f << "#-------------------------------------------------\n"
        << "#\n"
        << "# Project created by QtCreator 2010-12-19T16:24:53\n"
        << "#\n"
        << "#-------------------------------------------------\n"
        << "QT       += core\n"
        << "QT       -= gui\n"
        << "LIBS     += -lwt -lboost_regex\n"
        << "TARGET = ToolTestQtCreatorProFileWebsite\n"
        << "CONFIG   += console\n"
        << "CONFIG   -= app_bundle\n"
        << "TEMPLATE = app\n"
        << "SOURCES += wtmain.cpp \\\n"
        << "    profile.cpp\n"
        << "HEADERS += \\\n"
        << "    profile.h";
    }
    {
      std::ofstream f(mypath2);
      f << "#-------------------------------------------------\n"
        << "#\n"
        << "# Project created by QtCreator 2010-12-19T16:24:53\n"
        << "#\n"
        << "#-------------------------------------------------\n"
        << "QT       -= core\n"
        << "QT       -= gui\n"
        << "LIBS     += -lboost_regex\n"
        << "TARGET = ToolTestQtCreatorProFileConsole\n"
        << "CONFIG   += console\n"
        << "CONFIG   -= app_bundle\n"
        << "TEMPLATE = app\n"
        << "SOURCES += main.cpp \\\n"
        << "    profile.cpp\n"
        << "HEADERS += \\\n"
        << "    profile.h";
    }
    //Check the project file
    const boost::shared_ptr<const QtCreatorProFile> p1(new QtCreatorProFile(mypath1));
    const boost::shared_ptr<const QtCreatorProFile> p2(new QtCreatorProFile(mypath2));
    fileio::FileIo().DeleteFile(mypath1.c_str());
    fileio::FileIo().DeleteFile(mypath2.c_str());
  }
  //Test conditionals
  {
    //Create a project file
    const std::string mypath { fileio::FileIo().GetTempFileName() };
    {
      std::ofstream f(mypath);
      f
        << "QT       += core\n"
        << "unix {\n"
        << "SOURCES += \\\n"
        << "    unix_main.cpp \\\n"
        << "}\n"
        << "win32 {\n"
        << "TARGET = TestTarget\n"
        << "SOURCES += win_main.cpp\n"
        << "}\n"
        << "SOURCES += profile.cpp\n"
        << "HEADERS += \\\n"
        << "    profile.h";
    }
    //Check the project file
    const QtCreatorProFile p(mypath);
    assert(p.GetQt().size() == 1);
    assert(p.GetQt().count("core"));
    assert(p.GetSources().size() == 3);
    assert(p.GetSources().count("unix_main.cpp"));
    assert(p.GetSources().count("win_main.cpp"));
    assert(p.GetSources().count("profile.cpp"));
    assert(p.GetHeaders().size() == 1);
    assert(p.GetHeaders().count("profile.h"));

    //Test operator<<
    {
      std::stringstream ss;
      ss << p << '\n';
    }
    //Test operator==
    {
      QtCreatorProFile q(mypath);
      assert(p == q);
    }
    fileio::FileIo().DeleteFile(mypath.c_str());
  }
}
#endif

std::ostream& ribi::operator<<(std::ostream& os, const QtCreatorProFile& p)
{
  os << "\n";
  for (const std::string pri: p.GetPriFiles())
  {
    os << "include(" << pri << ")" << '\n';
  }
  {
    const std::vector<
      std::pair<
        std::string, boost::function<const std::set<std::string>& (const QtCreatorProFile&)>
        >
      > v = {
        { "CONFIG", &QtCreatorProFile::GetConfig },
        { "DEFINES", &QtCreatorProFile::GetDefines },
        { "FORMS", &QtCreatorProFile::GetForms },
        { "HEADERS", &QtCreatorProFile::GetHeaders },
        { "INCLUDEPATH", &QtCreatorProFile::GetIncludepath },
        { "LIBS", &QtCreatorProFile::GetLibs },
        { "OTHER_FILES", &QtCreatorProFile::GetOtherFiles },
        { "QMAKE_CXXFLAGS", &QtCreatorProFile::GetQmakeCxxflags },
        { "QT", &QtCreatorProFile::GetQt},
        { "RESOURCES", &QtCreatorProFile::GetResources },
        { "SOURCES", &QtCreatorProFile::GetSources },
        { "TARGET", &QtCreatorProFile::GetTarget },
        { "TEMPLATE", &QtCreatorProFile::GetTemplate }
      };

    std::for_each(v.begin(),v.end(),
      [&os,&p](const std::pair<std::string, boost::function<const std::set<std::string>& (const QtCreatorProFile&)> >& pair)
      {
        const std::set<std::string>& w = pair.second(p);
        if (!w.empty())
        {
          os << pair.first << " += \\\n";
          if (w.size() > 1)
          {
            std::transform(w.begin(),--w.end(),std::ostream_iterator<std::string>(os," \\\n"),
              [](const std::string& s) { return "    " + s; } );
          }
          os << "    " + (*(--w.end())) + '\n';
          os << "\n";
        }
      }
    );
  }
  os << "\n";
  os << "#--------------------------------------------------------------------------\n";
  os << "# This file was created by:\n";
  os << "#\n";
  {
    const std::vector<std::string> v = p.GetAbout().CreateAboutText();
    std::transform(v.begin(),v.end(),std::ostream_iterator<std::string>(os,"\n"),
      [](const std::string& s) { return "# " + s; } );
  }
  os << "#\n";
  os << "#\n";
  os << "#\n";
  {
    const std::vector<std::string> v = p.GetAbout().CreateLicenceText();
    std::transform(v.begin(),v.end(),std::ostream_iterator<std::string>(os,"\n"),
      [](const std::string& s) { return "# " + s; } );
  }
  os << "#--------------------------------------------------------------------------";
  return os;
}

bool ribi::operator==(const QtCreatorProFile& lhs, const QtCreatorProFile& rhs)
{
  return
       lhs.m_config == rhs.m_config
    && lhs.m_defines == rhs.m_defines
    && lhs.m_forms == rhs.m_forms
    && lhs.m_headers == rhs.m_headers
    && lhs.m_includepath == rhs.m_includepath
    && lhs.m_libs == rhs.m_libs
    && lhs.m_other_files == rhs.m_other_files
    && lhs.m_pro_filename == rhs.m_pro_filename
    && lhs.m_qmake_cxxflags == rhs.m_qmake_cxxflags
    && lhs.m_qt == rhs.m_qt
    && lhs.m_resources == rhs.m_resources
    && lhs.m_target == rhs.m_target
    && lhs.m_template == rhs.m_template
    && lhs.m_sources == rhs.m_sources;
}

 

 

 

 

 

./CppQtCreatorProFile/qtcreatorprofilezipscript.h

 

//---------------------------------------------------------------------------
/*
QtCreatorProFile, class to parse Qt Project files
Copyright (C) 2010-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtCreatorProFile.htm
//---------------------------------------------------------------------------
#ifndef QTCREATORPROFILEZIPSCRIPT
#define QTCREATORPROFILEZIPSCRIPT

#include <set>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/checked_delete.hpp>
#include <boost/shared_ptr.hpp>
#include "qtcreatorprofile.h"
#pragma GCC diagnostic pop

namespace ribi {

///Create a shell script to zip a Qt Creator .pro file
struct QtCreatorProFileZipScript
{
  QtCreatorProFileZipScript(
    const boost::shared_ptr<const ribi::QtCreatorProFile> pro_file
  );
  QtCreatorProFileZipScript(const QtCreatorProFileZipScript&) = delete;
  QtCreatorProFileZipScript& operator=(const QtCreatorProFileZipScript&) = delete;

  ///Create a script to zip all .pro files (and all they refer to) in a folder
  static std::string CreateScript(const std::string& source_folder);

  ///Obtain this class its About information
  static About GetAbout() noexcept;

  ///Obtain all filenames
  const std::set<std::string>& GetFilenames() const { return m_filenames; }

  ///Obtain the .pro file
  //const boost::shared_ptr<const QtCreatorProFile> GetProFile() const { return m_pro_file; }
  const std::string& GetProFileName() const { return m_pro_file_name; }

  ///Obtain this class its version
  static std::string GetVersion() noexcept;

  ///Obtain this class its version history
  static std::vector<std::string> GetVersionHistory() noexcept;

  static boost::shared_ptr<QtCreatorProFileZipScript> Merge(
    const std::vector<boost::shared_ptr<const QtCreatorProFileZipScript> >& v);

  ///Set all filenames
  void SetFilenames(const std::set<std::string>& filenames) { m_filenames = filenames; }

  private:
  ///Used when merging
  QtCreatorProFileZipScript(
    const std::set<std::string>& filenames,
    const std::string& pro_file_name);

  ///Be sure the class is correctly deleted
  ~QtCreatorProFileZipScript() noexcept {}
  friend void boost::checked_delete<>(QtCreatorProFileZipScript* x);

  ///All the files used by the QtCreatorProFile
  std::set<std::string> m_filenames;

  ///The original .pro file its filename
  const std::string m_pro_file_name;
  //const boost::shared_ptr<const QtCreatorProFile> m_pro_file;

  ///Create a QtCreatorProFile from every filename
  static std::vector<boost::shared_ptr<QtCreatorProFile> > CreateProFiles(const std::vector<std::string>& pro_files);

  ///Extract a QtCreatorProFile its filenames
  const std::set<std::string> ExtractFilenames(
    const boost::shared_ptr<const QtCreatorProFile> & pro_file) const;

  ///Get all the .pro files in a folder
  //From http://www.richelbilderbeek.nl/CppGetProFilesInFolder.htm

  static std::vector<std::string> GetProAndPriFilesInFolder(const std::string& folder);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os,const QtCreatorProFileZipScript& script) noexcept;
};

std::ostream& operator<<(std::ostream& os,const QtCreatorProFileZipScript& script) noexcept;

} //~namespace ribi

#endif // QTCREATORPROFILEZIPSCRIPT

 

 

 

 

 

./CppQtCreatorProFile/qtcreatorprofilezipscript.cpp

 

//---------------------------------------------------------------------------
/*
QtCreatorProFile, class to parse Qt Project files
Copyright (C) 2010-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppQtCreatorProFile.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "qtcreatorprofilezipscript.h"

#include <fstream>
#include <functional>
#include <iterator>
#include <set>

#include <boost/xpressive/xpressive.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>

#include <QDir>

#include "fileio.h"
#include "qrcfile.h"
#include "qtcreatorprofile.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop

struct PathOrdering
{
  bool operator()(const std::string& lhs, const std::string& rhs)
  {
    //Shortest files first
    if (lhs.size() < rhs.size()) return true;
    //Order same-length files alphabetically
    if (lhs.size() == rhs.size() && lhs < rhs) return true;
    return false;
  }
};


ribi::QtCreatorProFileZipScript::QtCreatorProFileZipScript(
  const boost::shared_ptr<const QtCreatorProFile> pro_file)
  : m_filenames(ExtractFilenames(pro_file)),
    m_pro_file_name(pro_file->GetQtCreatorProFilename())

{
  #ifndef NDEBUG
  ribi::QtCreatorProFileZipScript::Test();
  assert(fileio::FileIo().IsUnixPath(m_pro_file_name));
  assert(pro_file);
  for (const auto& s: m_filenames)
  {
    assert(ribi::fileio::FileIo().IsRegularFile(s));
  }
  #endif
}

ribi::QtCreatorProFileZipScript::QtCreatorProFileZipScript(
  const std::set<std::string>& filenames,
  const std::string& pro_file_name)
  : m_filenames(filenames),
    m_pro_file_name(pro_file_name)
{

}

std::vector<boost::shared_ptr<ribi::QtCreatorProFile> > ribi::QtCreatorProFileZipScript::CreateProFiles(
  const std::vector<std::string>& filenames)
{
  std::vector<boost::shared_ptr<ribi::QtCreatorProFile> > pro_files;
  for (const std::string& filename: filenames)
  {
    assert(ribi::fileio::FileIo().IsRegularFile(filename));
    const boost::shared_ptr<ribi::QtCreatorProFile> pro_file(new ribi::QtCreatorProFile(filename));
    assert(pro_file);
    pro_files.push_back(pro_file);
  }
  return pro_files;
}

std::string ribi::QtCreatorProFileZipScript::CreateScript(const std::string& source_folder)
{
  if (!fileio::FileIo().IsFolder(source_folder))
  {
    std::stringstream s;
    s << "QtCreatorProFileZipScript::CreateScript: folder '" << source_folder << "' not found";
    throw std::runtime_error(s.str().c_str());
  }
  if (source_folder.find('\\') != std::string::npos)
  {
    std::stringstream s;
    s << "QtCreatorProFileZipScript::CreateScript: folder '" << source_folder << "' contains Windows"
      << "path seperators. Use slash instead of backslash";
    throw std::runtime_error(s.str().c_str());
  }
  if (source_folder.substr(0,6) != "../../")
  {
    std::stringstream s;
    s << "QtCreatorProFileZipScript::CreateScript: folder '" << source_folder << "' does"
      << "not start with '../../'. Change the folder's name accordingly";
    throw std::runtime_error(s.str().c_str());
  }
  assert(fileio::FileIo().IsFolder(source_folder));
  assert(source_folder.substr(0,6) == "../../");
  assert(fileio::FileIo().IsUnixPath(source_folder));

  //Also include .pri files in that folder
  std::vector<std::string> pro_filenames = GetProAndPriFilesInFolder(source_folder);

  //Add the .pri files in the .pro files
  {
    std::vector<std::string> w(pro_filenames);
    for (const std::string pro_filename: pro_filenames)
    {
      assert(ribi::fileio::FileIo().IsUnixPath(pro_filename));

      const std::string full_pro_filename
        = source_folder.empty()
        ? std::string()
        : source_folder + '/' + pro_filename
      ;
      #ifndef NDEBUG
      if (!ribi::fileio::FileIo().IsRegularFile(full_pro_filename))
      {
        TRACE("ERROR");
        TRACE(full_pro_filename);
      }
      #endif
      assert(ribi::fileio::FileIo().IsRegularFile(full_pro_filename));
      assert(ribi::fileio::FileIo().IsUnixPath(full_pro_filename));

      const boost::shared_ptr<QtCreatorProFile> pro_file(
        new QtCreatorProFile(full_pro_filename)
      );

      assert(pro_file);
      //Copy its .pri files to be scanned
      for (const std::string pri_file: pro_file->GetPriFiles())
      {
        assert(ribi::fileio::FileIo().IsUnixPath(pri_file));
        w.push_back(pri_file);
      }
    }
    std::swap(w,pro_filenames);
  }

  //Create the scripts by merging QtCreatorProFiles
  std::vector<boost::shared_ptr<const QtCreatorProFileZipScript>> scripts;

  for (const std::string& pro_filename: pro_filenames)
  {
    assert(ribi::fileio::FileIo().IsUnixPath(pro_filename));

    const std::string full_pro_filename
      = fileio::FileIo().SimplifyPath(
        source_folder
      + '/'
      + pro_filename
      )
    ;
    #ifndef NDEBUG
    if (!ribi::fileio::FileIo().IsRegularFile(full_pro_filename))
    {
      TRACE("ERROR");
      TRACE(full_pro_filename);
      TRACE(source_folder);
      TRACE(pro_filename);
      TRACE("BREAK");
    }
    if (!ribi::fileio::FileIo().IsUnixPath(full_pro_filename))
    {
      TRACE("ERROR");
      TRACE(full_pro_filename);
      TRACE(source_folder);
      TRACE(pro_filename);
      TRACE("BREAK");
    }
    #endif

    assert(ribi::fileio::FileIo().IsRegularFile(full_pro_filename));
    assert(fileio::FileIo().IsUnixPath(full_pro_filename));
    const boost::shared_ptr<QtCreatorProFile> pro_file(
      new QtCreatorProFile(full_pro_filename));
    assert(pro_file);

    const boost::shared_ptr<QtCreatorProFileZipScript> script(
      new QtCreatorProFileZipScript(pro_file));
    assert(script);

    scripts.push_back(script);
  }


  const boost::shared_ptr<QtCreatorProFileZipScript> merged_script
    = ribi::QtCreatorProFileZipScript::Merge(scripts);
  if (!merged_script)
  {
    return "Folder does not contain any .pro files";
  }
  else
  {
    std::stringstream script;
    script << *merged_script;
    return script.str();
  }
}


const std::set<std::string> ribi::QtCreatorProFileZipScript::ExtractFilenames(
  const boost::shared_ptr<const QtCreatorProFile>& pro_file) const
{
  assert(pro_file);

  std::vector<std::string> v;
  std::copy(pro_file->GetForms().begin(),pro_file->GetForms().end(),std::back_inserter(v));
  std::copy(pro_file->GetHeaders().begin(),pro_file->GetHeaders().end(),std::back_inserter(v));
  std::copy(pro_file->GetOtherFiles().begin(),pro_file->GetOtherFiles().end(),std::back_inserter(v));
  std::copy(pro_file->GetResources().begin(),pro_file->GetResources().end(),std::back_inserter(v));
  std::copy(pro_file->GetSources().begin(),pro_file->GetSources().end(),std::back_inserter(v));


  //Copy all resources
  for (const std::string qrc_filename_raw: pro_file->GetResources())
  {
    assert(ribi::fileio::FileIo().IsUnixPath(qrc_filename_raw));

    const std::string qrc_filename_full
        = qrc_filename_raw.size() < 7 || qrc_filename_raw.substr(0,6) != "../../"
        ? ribi::fileio::FileIo().GetPath(pro_file->GetQtCreatorProFilename())
        //? boost::filesystem::path(pro_file->GetQtCreatorProFilename()).parent_path().string()
            + "/" + qrc_filename_raw
        : qrc_filename_raw;

    assert(qrc_filename_full.size() > 6);
    assert(qrc_filename_full.substr(0,6) == "../../");
    assert(ribi::fileio::FileIo().IsUnixPath(qrc_filename_full));

    if (!ribi::fileio::FileIo().IsRegularFile(qrc_filename_full))
    {
      const std::string s = "Warning: Resource file \'" + qrc_filename_full + "\' not found";
      TRACE(s);
      continue;
    }
    assert(ribi::fileio::FileIo().IsRegularFile(qrc_filename_full));
    assert(qrc_filename_full.size() > 6 && qrc_filename_full.substr(0,6) == "../../");
    assert(qrc_filename_full.size() > 7 && qrc_filename_full.substr(0,7) != "../../.");
    const boost::shared_ptr<const QrcFile> qrc_file(
      new QrcFile(qrc_filename_full));
    assert(qrc_file);

    //BUG: QrcFile supplies its files without a full path
    //std::copy(qrc_file->GetFiles().begin(),qrc_file->GetFiles().end(),std::back_inserter(v));

    for (const std::string& filename : qrc_file->GetFiles())
    {
      assert(ribi::fileio::FileIo().IsUnixPath(filename));

      const std::string full_resource_item_name
        = ribi::fileio::FileIo().GetPath(qrc_filename_full) + "/" + filename;
      //  = boost::filesystem::path(qrc_filename_full).parent_path().string() + "/" + filename;

      assert(ribi::fileio::FileIo().IsRegularFile(full_resource_item_name));
      assert(ribi::fileio::FileIo().IsUnixPath(full_resource_item_name));

      v.push_back(full_resource_item_name);
    }
  }

  //Add paths if needed
  std::vector<std::string> filenames;
  assert(pro_file);
  assert(ribi::fileio::FileIo().IsRegularFile(pro_file->GetQtCreatorProFilename()));
  filenames.push_back(pro_file->GetQtCreatorProFilename());
  for (const std::string filename: v)
  {
    if (!filename.empty() && (filename[0] == '/' || filename[0] == '.'))
    {
      #ifndef NDEBUG
      if (!ribi::fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
        TRACE("BREAK");
      }
      #endif
      assert(ribi::fileio::FileIo().IsRegularFile(filename));
      assert(ribi::fileio::FileIo().IsUnixPath(filename));
      filenames.push_back(filename);
    }
    else if (!filename.empty() && filename[0] != '/' && filename[0] != '.')
    {
      //Add full path
      const std::string s
        = ribi::fileio::FileIo().GetPath(pro_file->GetQtCreatorProFilename());
      //  = boost::filesystem::path(pro_file->GetQtCreatorProFilename()).parent_path().string();

      assert(s.size() > 6);
      assert(ribi::fileio::FileIo().IsUnixPath(s));

      const std::string t = s + "/" + filename;
      //TRACE(t);
      assert(ribi::fileio::FileIo().IsRegularFile(t));
      assert(ribi::fileio::FileIo().IsUnixPath(t));
      filenames.push_back(t);
    }
  }

  #ifndef NDEBUG
  for (const auto& s: filenames) { assert(ribi::fileio::FileIo().IsRegularFile(s)); }
  #endif // NDEBUG
  for (std::string& s: filenames) { s = fileio::FileIo().SimplifyPath(s); }
  #ifndef NDEBUG
  for (const auto& s: filenames) { assert(ribi::fileio::FileIo().IsRegularFile(s)); }
  #endif // NDEBUG
  std::sort(filenames.begin(),filenames.end());
  filenames.erase( std::unique(filenames.begin(),filenames.end()), filenames.end() );

  std::set<std::string> s;
  std::copy(filenames.begin(),filenames.end(),std::inserter(s,s.begin()));
  return s;
}

ribi::About ribi::QtCreatorProFileZipScript::GetAbout() noexcept
{
  ribi::About a(
    "Richel Bilderbeek",
    "QtCreatorProFileZipScript",
    "class to create a zip file from a .pro file",
    "the 19th of May 2013",
    "2013-2015",
    "http://www.richelbilderbeek.nl/CppQtCreatorProFileZipScript.htm",
    GetVersion(),
    GetVersionHistory());
  a.AddLibrary("QrcFile version: " + QrcFile::GetVersion());
  a.AddLibrary("QtCreatorProFile version: " + QtCreatorProFile::GetVersion());
  a.AddLibrary("Trace version: " + Trace::GetVersion());
  return a;
}

//std::vector<std::string> ribi::QtCreatorProFileZipScript::GetProFilesInFolder(const std::string& folder)
//{
//  assert(fileio::FileIo().IsFolder(folder));
//  return ribi::fileio::FileIo().GetFilesInFolderByRegex(folder,".*\\.(pro)\\>");
//}

std::vector<std::string> ribi::QtCreatorProFileZipScript::GetProAndPriFilesInFolder(const std::string& folder)
{
  assert(fileio::FileIo().IsFolder(folder));
  const std::vector<std::string> v = ribi::fileio::FileIo().GetFilesInFolderByRegex(folder,".*\\.(pro|pri)\\>");
  return v;
}

std::string ribi::QtCreatorProFileZipScript::GetVersion() noexcept
{
  return "2.0";
}

std::vector<std::string> ribi::QtCreatorProFileZipScript::GetVersionHistory() noexcept
{
  return {
    "2013-05-19: version 1.0: initial version",
    "2013-08-19: version 1.1: replaced Boost.Regex by Boost.Xpressive",
    "2013-12-05: version 1.2: add support for .pri files"
    "2014-04-25: version 1.3: fixed SimplifiedPath bug",
    "2014-05-02: version 2.0: use UNIX path seperators only"
  };
}

boost::shared_ptr<ribi::QtCreatorProFileZipScript> ribi::QtCreatorProFileZipScript::Merge(
  const std::vector<boost::shared_ptr<const QtCreatorProFileZipScript> >& scripts)
{
  boost::shared_ptr<ribi::QtCreatorProFileZipScript> p;
  if (scripts.empty()) return p;

  std::set<std::string> all_filenames;
  std::string pro_file_name;

  for (const boost::shared_ptr<const QtCreatorProFileZipScript>& script: scripts)
  {
    const auto filenames = script->GetFilenames();
    all_filenames.insert(filenames.begin(),filenames.end());
    pro_file_name = script->GetProFileName(); //Just for having something
  }
  p.reset(new QtCreatorProFileZipScript(all_filenames,pro_file_name));
  assert(p);
  return p;
}


#ifndef NDEBUG
void ribi::QtCreatorProFileZipScript::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  ribi::fileio::FileIo();

  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Test basic functions on this project with going two folders down
  const std::vector<std::string> pro_file_names
    =
    {
      "../../Tools/ToolCreateQtProjectZipFile/ToolCreateQtProjectZipFileDesktop.pro",
      "../../Tools/ToolCodeToHtml/ToolCodeToHtmlDesktop.pro",
      "../../Tools/ToolKalmanFilterer/ToolKalmanFiltererDesktop.pro",
      "../../ProjectRichelBilderbeek/ProjectRichelBilderbeek/ProjectRichelBilderbeekDesktop.pro"
    };
  for (const std::string& pro_file_name: pro_file_names)
  {
    if (!ribi::fileio::FileIo().IsRegularFile(pro_file_name)) continue;

    assert(ribi::fileio::FileIo().IsRegularFile(pro_file_name));
    const boost::shared_ptr<const QtCreatorProFile> pro_file(
      new QtCreatorProFile(pro_file_name) );
    assert(pro_file);

    const boost::shared_ptr<const QtCreatorProFileZipScript> zip_script(
      new QtCreatorProFileZipScript(pro_file) );
    assert(zip_script);

    const std::set<std::string> filenames = zip_script->GetFilenames();
    for (const std::string& filename: filenames)
    {
      if (!ribi::fileio::FileIo().IsRegularFile(filename))
      {
        const std::string warning = "Warning: file \'" + filename + "\' not found";
        TRACE(warning);
        continue;
      }
      assert(ribi::fileio::FileIo().IsRegularFile(filename));
    }
  }
  //Test that GetProFilesInFolder detects an additional .pro file
  //being added to a folder
  {
    const std::string tmp_pro_filename { fileio::FileIo().GetTempFileName(".pro") };

    //Count the current number of .pro files
    const std::size_t n = GetProAndPriFilesInFolder("").size();

    //Add a .pro file
    {
      std::ofstream f(tmp_pro_filename.c_str());
      f.close();
      assert(ribi::fileio::FileIo().IsRegularFile(tmp_pro_filename));
    }

    //Count the current number of .pro and .pri files again
    const std::size_t p = GetProAndPriFilesInFolder("").size();
    #ifndef NDEBUG
    if (n != p-1)
    {
      TRACE("ERROR: GetProFilesInFolder does not detect .pro files correctly");
    }
    #endif
    assert(n == p - 1);
    fileio::FileIo().DeleteFile(tmp_pro_filename);
    const std::size_t q = GetProAndPriFilesInFolder("").size();
    assert(n == q);
  }
}
#endif

std::ostream& ribi::operator<<(std::ostream& os,const QtCreatorProFileZipScript& script) noexcept
{
  #ifndef NDEBUG
  {
    const std::string s = script.GetProFileName();
    assert(s.size() > 6);
    assert(s.substr(0,6) == "../../");
    assert(ribi::fileio::FileIo().IsUnixPath(s));
  }
  #endif


  os << "#!/bin/sh" << '\n';
  os << "# Created from file '"
     << script.GetProFileName()
     << "\'" << '\n';
  os << '\n';

  //if (!m_folder_name_for_sloccount.empty())
  //{
  //  os << '\n'
  //     << "echo \"Creating a sloccount file\"" << '\n'
  //     << "sloccount " << m_folder_name_for_sloccount << " > sloccount.txt" << '\n'
  //     << '\n';
  //}
  //if (!m_doxygen_filename.empty())
  //{
  //  os << "echo \"Creating documentation\"" << '\n'
  //     << "doxygen \"" << m_doxygen_filename << "\"" << '\n';
  //}
  //os << '\n';
  //os << "echo \"Removing user information\"" << '\n';
  //os << "rm *.user" << '\n';
  //os << '\n';
  //os << "echo \"Removing possible temp file\"" << '\n';
  //os << "rm copy.txt" << '\n';
  //os << "rm tmp.txt" << '\n';
  //os << '\n';

  os << "echo \"Creating of all folders\"" << '\n';
  os << '\n';
  os << "mkdir Projects" << '\n';

  //file names with full path
  const auto file_names_vector = script.GetFilenames();
  const std::set<std::string,PathOrdering> file_names(
    file_names_vector.begin(),file_names_vector.end()
  );

  std::set<std::string,PathOrdering> folder_names;
  //Add the folders added by the .pro file
  for (const std::string filename: file_names)
  {
    assert(ribi::fileio::FileIo().IsRegularFile(filename));
    assert(ribi::fileio::FileIo().IsUnixPath(filename));

    std::string s = ribi::fileio::FileIo().GetPath(filename);

    //Foldernames like '../../Classes/CppQrcFile' must be ignored or not occur here.
    if (!(s[ s.size() - 1] != '.' || s[ s.size() - 2] != '.')) continue;
    while (!s.empty())
    {
      const std::size_t old_len = s.size();
      const std::string t = fileio::FileIo().SimplifyPath(s);
      folder_names.insert(t);
      s = ribi::fileio::FileIo().GetPath(s);
      assert(fileio::FileIo().IsUnixPath(s));
      const std::size_t new_len = s.size();
      if (new_len == old_len) { s = ""; }
    }
  }


  for (const std::string& s: folder_names)
  {
    if (s.size() > 6 && s.substr(0,6) == "../../")
    {
      const std::string folder = s.substr(6,s.size() - 6);
      assert(ribi::fileio::FileIo().IsUnixPath(folder));
      if ( folder[ folder.size() - 1] == '.'
        || folder[ folder.size() - 2] == '.'
      )
      {
        TRACE("ERROR");
        TRACE(folder);
        TRACE("BREAK");
      }
      assert(folder[ folder.size() - 1] != '.');
      assert(folder[ folder.size() - 2] != '.');
      assert(folder[ folder.size() - 3] != '.');
      assert(folder[ folder.size() - 4] != '.');
      os << "mkdir Projects" << fileio::FileIo().GetPathSeperator() << folder << '\n';
    }
  }

  os << '\n';
  os << "echo \"Copying files\"" << '\n';
  os << '\n';

  for (const std::string& s: file_names)
  {
    assert(ribi::fileio::FileIo().IsUnixPath(s));

    if (s.size() > 6 && s.substr(0,6) == "../../")
    {
      os << "cp " << s << " Projects/" << s.substr(6,s.size() - 6) << '\n';
    }
    else if (s.size() > 3 && s.substr(0,1) != ".")
    {
      //A file in the .pro file its folder
      os << "cp " << s << " Projects/"
        << ribi::fileio::FileIo().GetPath(script.GetProFileName())
        << s << '\n'
      ;
    }
  }

  os << '\n';
  os << "FILENAME=\""
     << ribi::fileio::FileIo().GetPath( script.GetProFileName() )
     //<< boost::filesystem::path( script.GetProFileName() ).parent_path().string()
     << "Source\"" << '\n';
  os << "ZIP_FILENAME=$FILENAME\".zip\"" << '\n';
  os << '\n';
  os << "echo \"Compressing files\"" << '\n';
  os << '\n';
  os << "zip -r $FILENAME Projects" << '\n';
  os << '\n';
  os << "echo \"Cleaning up\"" << '\n';
  os << '\n';
  os << "echo \"Emptying subfolders\"" << '\n';
  os << '\n';

  std::for_each(folder_names.rbegin(),folder_names.rend(),
    [&os](const std::string& s)
    {
      if (s.size() > 6 && s.substr(0,6) == "../../")
      {
         os << "rm Projects/" + s.substr(6,s.size() - 6) << "/*.*" << '\n';
      }
    }
  );

  os << "rm Projects/*.*" << '\n';

  std::for_each(folder_names.rbegin(),folder_names.rend(),
    [&os](const std::string& s)
    {
      if (s.size() > 6 && s.substr(0,6) == "../../")
      {
        os << "rmdir Projects/" << s.substr(6,s.size()-6) << '\n';
      }
    }
  );
  os << "rmdir Projects" << '\n';
  os << '\n';
  os << "echo \"Done\"" << '\n';
  os << '\n';
  {
    const std::vector<std::string> w
      = ribi::QtCreatorProFileZipScript::GetAbout().CreateAboutText();
    std::transform(w.begin(),w.end(),
    std::ostream_iterator<std::string>(os,"\n"),
      [](const std::string& s)
      {
        return "# " + s;
      }
    );
  }
  return os;
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml