From 43243ae162a01b8db7a481db8ab3b183afd2efab Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 5 Jul 2018 00:33:34 +0200 Subject: [PATCH] Enabled Qt-less unit tests, some basic implementation of Qt-less threads based on pthread and an atomics library. A lot missing. --- src/klayout.pro | 4 +- src/lay/lay/layApplication.cc | 3 +- src/lay/lay/laySystemPaths.cc | 50 +------ src/lay/lay/laySystemPaths.h | 6 - src/tl/tl/tl.pro | 4 + src/tl/tl/tlFileUtils.cc | 41 ++++++ src/tl/tl/tlFileUtils.h | 5 + src/tl/tl/tlProgress.cc | 2 +- src/tl/tl/tlThreads.cc | 229 +++++++++++++++++++++++++++++++ src/tl/tl/tlThreads.h | 112 +++++++++++---- src/tl/unit_tests/tlString.cc | 2 +- src/unit_tests/unit_test_main.cc | 110 +++++++++++---- src/with_all_libs.pri | 35 +++-- 13 files changed, 474 insertions(+), 129 deletions(-) diff --git a/src/klayout.pro b/src/klayout.pro index 614ca277c..60855e611 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -11,12 +11,12 @@ SUBDIRS = \ lib \ buddies \ plugins \ + unit_tests \ !equals(HAVE_QT, "0") { # TODO: make unit_tests capable of running without Qt SUBDIRS += \ - unit_tests \ klayout_main \ laybasic \ lay \ @@ -94,7 +94,7 @@ plugins.depends += lib rdb db lym.depends += gsi $$LANG_DEPENDS lay.depends += laybasic ant img edt lym klayout_main.depends += plugins $$MAIN_DEPENDS - unit_tests.depends += plugins $$MAIN_DEPENDS } +unit_tests.depends += plugins $$MAIN_DEPENDS diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 8f13688ac..a6a44abc4 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -61,6 +61,7 @@ #include "tlInternational.h" #include "tlHttpStream.h" #include "tlArch.h" +#include "tlFileUtils.h" #include #include @@ -219,7 +220,7 @@ ApplicationBase::ApplicationBase (bool non_ui_mode) m_appdata_path = lay::get_appdata_path (); // get the installation path - m_inst_path = lay::get_inst_path (); + m_inst_path = tl::get_inst_path (); } void diff --git a/src/lay/lay/laySystemPaths.cc b/src/lay/lay/laySystemPaths.cc index 26d273e78..451976878 100644 --- a/src/lay/lay/laySystemPaths.cc +++ b/src/lay/lay/laySystemPaths.cc @@ -22,6 +22,7 @@ #include "laySystemPaths.h" +#include "tlFileUtils.h"l" #include "tlString.h" #include @@ -68,53 +69,6 @@ get_appdata_path () return tl::to_string (appdata_dir.absoluteFilePath (appdata_folder)); } -static std::string -get_inst_path_internal () -{ - // Note: the QCoreApplication::applicationDirPath cannot be used before - // a QApplication object is instantiated. Hence this custom implementation. -#ifdef _WIN32 - - wchar_t buffer[MAX_PATH]; - int len; - if ((len = GetModuleFileName(NULL, buffer, MAX_PATH)) > 0) { - QFileInfo fi (QString::fromUtf16 ((const ushort *) buffer, len)); - return tl::to_string (fi.absolutePath ()); - } - -#elif __APPLE__ - - char buffer[PROC_PIDPATHINFO_MAXSIZE]; - int ret = proc_pidpath (getpid (), buffer, sizeof (buffer)); - if (ret > 0) { - // TODO: does this correctly translate paths? (MacOS uses UTF-8 encoding with D-like normalization) - return tl::to_string (QFileInfo (QString::fromUtf8 (buffer)).absolutePath ()); - } - -#else - - QFileInfo proc_exe (tl::to_qstring (tl::sprintf ("/proc/%d/exe", getpid ()))); - if (proc_exe.exists () && proc_exe.isSymLink ()) { - return tl::to_string (QFileInfo (proc_exe.canonicalFilePath ()).absolutePath ()); - } - -#endif - - // As a fallback use QCoreApplication::applicationDirPath, which however is not - // available before QCoreApplication is initialized - return tl::to_string (QCoreApplication::applicationDirPath ()); -} - -std::string -get_inst_path () -{ - static std::string s_inst_path; - if (s_inst_path.empty ()) { - s_inst_path = get_inst_path_internal (); - } - return s_inst_path; -} - #ifdef _WIN32 static void get_other_system_paths (std::vector &p) @@ -198,7 +152,7 @@ get_klayout_path () split_path (tl::system_to_string (env), klayout_path); } else { get_other_system_paths (klayout_path); - klayout_path.push_back (get_inst_path ()); + klayout_path.push_back (tl::get_inst_path ()); } #endif diff --git a/src/lay/lay/laySystemPaths.h b/src/lay/lay/laySystemPaths.h index 2fcad3bd3..790c0ced7 100644 --- a/src/lay/lay/laySystemPaths.h +++ b/src/lay/lay/laySystemPaths.h @@ -41,12 +41,6 @@ namespace lay */ LAY_PUBLIC std::string get_appdata_path (); -/** - * @brief Gets the installation path - * The installation path is the path where the current application is installed. - */ -LAY_PUBLIC std::string get_inst_path (); - /** * @brief Gets the KLayout path * This is a path (in the sense of a search path - i.e. multiple paths) diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro index 371e6adbd..8e82e0c2e 100644 --- a/src/tl/tl/tl.pro +++ b/src/tl/tl/tl.pro @@ -8,6 +8,10 @@ DEFINES += MAKE_TL_LIBRARY LIBS += -lz +equals(HAVE_QT, "0") { + LIBS += -lpthread +} + equals(HAVE_CURL, "1") { LIBS += -lcurl win32 { diff --git a/src/tl/tl/tlFileUtils.cc b/src/tl/tl/tlFileUtils.cc index 39297aa56..a17e7d5a6 100644 --- a/src/tl/tl/tlFileUtils.cc +++ b/src/tl/tl/tlFileUtils.cc @@ -710,4 +710,45 @@ bool is_same_file (const std::string &a, const std::string &b) #endif } +static std::string +get_inst_path_internal () +{ +#ifdef _WIN32 + + wchar_t buffer[MAX_PATH]; + int len; + if ((len = GetModuleFileName (NULL, buffer, MAX_PATH)) > 0) { + return tl::absolute_path (tl::to_string (std::wstring (buffer))); + } + +#elif __APPLE__ + + char buffer[PROC_PIDPATHINFO_MAXSIZE]; + int ret = proc_pidpath (getpid (), buffer, sizeof (buffer)); + if (ret > 0) { + // TODO: does this correctly translate paths? (MacOS uses UTF-8 encoding with D-like normalization) + return tl::absolute_path (buffer); + } + +#else + + std::string pf = tl::sprintf ("/proc/%d/exe", getpid ()); + if (tl::file_exists (pf)) { + return tl::absolute_path (pf); + } + +#endif + tl_assert (false); +} + +std::string +get_inst_path () +{ + static std::string s_inst_path; + if (s_inst_path.empty ()) { + s_inst_path = get_inst_path_internal (); + } + return s_inst_path; +} + } diff --git a/src/tl/tl/tlFileUtils.h b/src/tl/tl/tlFileUtils.h index 648354132..2a1d2db2b 100644 --- a/src/tl/tl/tlFileUtils.h +++ b/src/tl/tl/tlFileUtils.h @@ -163,6 +163,11 @@ std::string TL_PUBLIC current_dir (); */ std::vector TL_PUBLIC split_path (const std::string &p, bool keep_last = false); +/** + * @brief Gets the path of the currently running process + */ +std::string TL_PUBLIC get_inst_path (); + } #endif diff --git a/src/tl/tl/tlProgress.cc b/src/tl/tl/tlProgress.cc index 2078a43eb..a1501caa9 100644 --- a/src/tl/tl/tlProgress.cc +++ b/src/tl/tl/tlProgress.cc @@ -61,7 +61,7 @@ ProgressAdaptor::prev () // --------------------------------------------------------------------------------------------- // Progress implementation -// Hint: we don't want the QThreadStorage take ownership over the object. Hence we don't +// Hint: we don't want the ThreadStorage take ownership over the object. Hence we don't // store a pointer but a pointer to a pointer. static tl::ThreadStorage s_thread_data; diff --git a/src/tl/tl/tlThreads.cc b/src/tl/tl/tlThreads.cc index 68f36ac68..0c9b782d9 100644 --- a/src/tl/tl/tlThreads.cc +++ b/src/tl/tl/tlThreads.cc @@ -20,3 +20,232 @@ */ +#if !defined(HAVE_QT) + +#include "tlThreads.h" +#include "tlLog.h" +#include "tlInternational.h" + +#include +#include + +namespace tl +{ + +// ------------------------------------------------------------------------------- +// WaitCondition implementation + +WaitCondition::WaitCondition () +{ + // @@@ +} + +bool WaitCondition::wait (Mutex *mutex, unsigned long /*time*/) +{ + mutex->unlock(); + // @@@ + mutex->lock(); + return true; +} + +void WaitCondition::wakeAll () +{ + // @@@ +} + +void WaitCondition::wakeOne () +{ + // @@@ +} + +// ------------------------------------------------------------------------------- +// Thread implementation + +class ThreadPrivateData +{ +public: + ThreadPrivateData () + : pthread (), initialized (false), return_code (0), running (false) + { + // .. nothing yet .. + } + + pthread_t pthread; + bool initialized; + void *return_code; + bool running; +}; + +void *start_thread (void *data) +{ + ((Thread *) data)->do_run (); + return 0; +} + +Thread::Thread () + : mp_data (new ThreadPrivateData ()) +{ + // .. nothing yet .. +} + +Thread::~Thread () +{ + delete mp_data; + mp_data = 0; +} + +void Thread::do_run () +{ + try { + mp_data->running = true; + run (); + mp_data->running = false; + } catch (tl::Exception &ex) { + tl::error << tr ("Exception from thread : ") << ex.msg (); + mp_data->running = false; + } catch (...) { + tl::error << tr ("Unspecific exception from thread"); + mp_data->running = false; + } +} + +void Thread::exit (int return_code) +{ + pthread_exit (reinterpret_cast (size_t (return_code))); +} + +bool Thread::isFinished () const +{ + if (! mp_data->initialized) { + return false; + } else { + return ! mp_data->running; + } +} + +bool Thread::isRunning () const +{ + if (! mp_data->initialized) { + return false; + } else { + return mp_data->running; + } +} + +void Thread::quit () +{ + exit (0); +} + +void Thread::start () +{ + if (isRunning ()) { + return; + } + + if (! mp_data->initialized) { + mp_data->initialized = true; + if (pthread_create (&mp_data->pthread, NULL, &start_thread, (void *) this) != 0) { + tl::error << tr ("Failed to create thread"); + } + } +} + +void Thread::terminate () +{ + if (isRunning () && pthread_cancel (mp_data->pthread) != 0) { + tl::error << tr ("Failed to terminate thread"); + } +} + +bool Thread::wait (unsigned long /*time*/) +{ + if (! mp_data->initialized) { + return true; + } + + // @@@ TODO: timed join + if (pthread_join (mp_data->pthread, &mp_data->return_code) != 0) { + tl::error << tr ("Could not join threads"); + } + return true; +} + +// ------------------------------------------------------------------------------- +// ThreadStorage implementation + +class ThreadStorageObjectList +{ +public: + ThreadStorageObjectList () { } + + ~ThreadStorageObjectList () + { + for (std::map::iterator i = m_objects.begin (); i != m_objects.end (); ++i) { + delete i->second; + } + m_objects.clear (); + } + + void add (void *index, ThreadStorageHolderBase *holder) + { + std::map::iterator h = m_objects.find (holder); + if (h != m_objects.end ()) { + delete h->second; + h->second = holder; + } else { + m_objects.insert (std::make_pair (index, holder)); + } + } + + ThreadStorageHolderBase *get (void *index) + { + std::map::const_iterator h = m_objects.find (index); + return h != m_objects.end () ? h->second : 0; + } + +private: + std::map m_objects; +}; + +static pthread_key_t s_storage_key; +static pthread_once_t s_keycreated = PTHREAD_ONCE_INIT; + +static void free_key (void *data) +{ + delete (ThreadStorageObjectList *) data; +} + +static void create_key () +{ + pthread_key_create (&s_storage_key, free_key); +} + +ThreadStorageBase::ThreadStorageBase () +{ + // .. nothing yet .. +} + +void ThreadStorageBase::add (ThreadStorageHolderBase *holder) +{ + pthread_once (&s_keycreated, create_key); + if (! pthread_getspecific (s_storage_key)) { + pthread_setspecific (s_storage_key, new ThreadStorageObjectList ()); + } + + ((ThreadStorageObjectList *) pthread_getspecific (s_storage_key))->add ((void *) this, holder); +} + +ThreadStorageHolderBase *ThreadStorageBase::holder () +{ + pthread_once (&s_keycreated, create_key); + if (! pthread_getspecific (s_storage_key)) { + return 0; + } else { + return ((ThreadStorageObjectList *) pthread_getspecific (s_storage_key))->get ((void *) this); + } +} + +} + +#endif diff --git a/src/tl/tl/tlThreads.h b/src/tl/tl/tlThreads.h index 89a5f32fd..2d778172f 100644 --- a/src/tl/tl/tlThreads.h +++ b/src/tl/tl/tlThreads.h @@ -32,6 +32,9 @@ # include # include # include +#else +// atomics taken from https://github.com/mbitsnbites/atomic +# include "atomic/spinlock.h" #endif namespace tl @@ -56,11 +59,10 @@ public: // The non-Qt version is a dummy implementation as threading is not supported (yet) class TL_PUBLIC Mutex + : public atomic::spinlock { public: - Mutex () { } - void lock () { } - void unlock () { } + Mutex () : atomic::spinlock () { } }; #endif @@ -88,10 +90,10 @@ public: class TL_PUBLIC WaitCondition { public: - WaitCondition () { } - bool wait (Mutex * /*mutex*/, unsigned long /*time*/ = std::numeric_limits::max ()) { return true; } - void wakeAll () { } - void wakeOne () { } + WaitCondition (); + bool wait (Mutex * /*mutex*/, unsigned long /*time*/ = std::numeric_limits::max ()); + void wakeAll (); + void wakeOne (); }; #endif @@ -136,23 +138,29 @@ public: #else -// TODO: this is a non-threaded dummy implementation +class ThreadPrivateData; + class TL_PUBLIC Thread { public: - Thread () { } - virtual ~Thread () { } + Thread (); + virtual ~Thread (); - void exit (int /*returnCode*/ = 0) { } - bool isFinished () const { return true; } - bool isRunning () const { return false; } - void quit () { } - void start () { run (); } - void terminate () { } - bool wait (unsigned long /*time*/ = std::numeric_limits::max ()) { return true; } + void exit (int /*returnCode*/ = 0); + bool isFinished () const; + bool isRunning () const; + void quit (); + void start (); + void terminate (); + bool wait (unsigned long /*time*/ = std::numeric_limits::max ()); protected: virtual void run () { } + +private: + friend void *start_thread (void *); + ThreadPrivateData *mp_data; + void do_run (); }; #endif @@ -175,21 +183,69 @@ public: #else -// TODO: this is the non-threaded dummy implementation -template -class TL_PUBLIC ThreadStorage +class TL_PUBLIC ThreadStorageHolderBase { public: - ThreadStorage () : m_t (), m_has_data (false) { } + ThreadStorageHolderBase (void *obj) : mp_obj (obj) { } + virtual ~ThreadStorageHolderBase () { } - bool hasLocalData () const { return m_has_data; } - T &localData () { return m_t; } - T localData () const { return m_t; } - void setLocalData (const T &data) { m_t = data; m_has_data = true; } +protected: + void *obj () { return mp_obj; } + void *mp_obj; +}; -private: - T m_t; - bool m_has_data; +template +class ThreadStorageHolder + : public ThreadStorageHolderBase +{ +public: + ThreadStorageHolder (T *t) : ThreadStorageHolderBase ((void *) t) { } + ~ThreadStorageHolder () { delete data (); } + T *data () { return (T *) obj (); } +}; + +class TL_PUBLIC ThreadStorageBase +{ +public: + ThreadStorageBase (); + +protected: + void add (ThreadStorageHolderBase *holder); + ThreadStorageHolderBase *holder (); + + const ThreadStorageHolderBase *holder () const + { + return (const_cast (this)->holder ()); + } +}; + +// TODO: this is the non-threaded dummy implementation +template +class ThreadStorage + : public ThreadStorageBase +{ +public: + ThreadStorage () : ThreadStorageBase () { } + + bool hasLocalData () const + { + return dynamic_cast *> (holder ()) != 0; + } + + T &localData () + { + return *(dynamic_cast *> (holder ())->data ()); + } + + T localData () const + { + return *(dynamic_cast *> (holder ())->data ()); + } + + void setLocalData (const T &data) + { + add (new ThreadStorageHolder (new T (data))); + } }; #endif diff --git a/src/tl/unit_tests/tlString.cc b/src/tl/unit_tests/tlString.cc index ee7a09bf8..4167a73ab 100644 --- a/src/tl/unit_tests/tlString.cc +++ b/src/tl/unit_tests/tlString.cc @@ -487,7 +487,7 @@ TEST(15) EXPECT_EQ (tl::to_string_from_local (tl::to_local ("Hällo\tWörld!").c_str ()), "Hällo\tWörld!"); EXPECT_EQ (std::string ("Ä").size (), size_t (2)); EXPECT_EQ (tl::to_string (std::wstring (L"Ä")), "Ä"); - EXPECT_EQ (tl::to_wstring (std::string ("Ä")).size (), 1); + EXPECT_EQ (tl::to_wstring (std::string ("Ä")).size (), size_t (1)); EXPECT_EQ (tl::to_string (tl::to_wstring ("Utf8 supports emoticons: \xF0\x9F\x98\x81\nand Umlauts: äüö")).c_str (), "Utf8 supports emoticons: \xF0\x9F\x98\x81\nand Umlauts: äüö"); EXPECT_EQ (tl::to_upper_case ("äÄüÜöÖß"), "ÄÄÜÜÖÖß"); diff --git a/src/unit_tests/unit_test_main.cc b/src/unit_tests/unit_test_main.cc index 384ffc4da..9fbdf968a 100644 --- a/src/unit_tests/unit_test_main.cc +++ b/src/unit_tests/unit_test_main.cc @@ -28,22 +28,31 @@ #include "tlStaticObjects.h" #include "tlTimer.h" #include "tlCommandLineParser.h" -#include "layApplication.h" -#include "laySystemPaths.h" -#include "layVersion.h" +#include "tlFileUtils.h" +#include "tlGlobPattern.h" #include "rba.h" #include "pya.h" #include "gsiDecl.h" #include "gsiExternalMain.h" +#include "dbStatic.h" +#include "dbInit.h" // This hard-links the GSI test classes #include "../gsi_test/gsiTestForceLink.h" -#include "version.h" +#if defined(HAVE_QT) -#include -#include -#include +# include "layApplication.h" +# include "laySystemPaths.h" +# include "layVersion.h" + +# include "version.h" + +# include +# include +# include + +#endif #if !defined(_WIN32) # include @@ -54,7 +63,7 @@ // required to force linking of the "ext", "lib" and "drc" module #include "libForceLink.h" -#if defined(HAVE_RUBY) +#if defined(HAVE_RUBY) && defined(HAVE_QT) #include "drcForceLink.h" #endif @@ -87,7 +96,7 @@ run_test (tl::TestBase *t, bool editable, bool slow, int repeat) } static int -run_tests (const std::vector &selected_tests, bool editable, bool non_editable, bool slow, int repeat, lay::ApplicationBase &app, bool gsi_coverage, const std::vector &class_names_vector) +run_tests (const std::vector &selected_tests, bool editable, bool non_editable, bool slow, int repeat, bool gsi_coverage, const std::vector &class_names_vector) { std::set class_names; class_names.insert (class_names_vector.begin (), class_names_vector.end ()); @@ -109,7 +118,11 @@ run_tests (const std::vector &selected_tests, bool editable, boo ut::noctrl << tl::replicate ("=", ut::TestConsole::instance ()->real_columns ()); ut::noctrl << "Running tests in " << mode << " mode ..."; - app.set_editable (e != 0); + + db::set_default_editable_mode (e != 0); +#if defined(HAVE_QT) + lay::ApplicationBase::instance ()->set_editable (e != 0); +#endif int failed = 0; std::vector failed_tests; @@ -339,6 +352,11 @@ run_tests (const std::vector &selected_tests, bool editable, boo static int main_cont (int &argc, char **argv) { + std::auto_ptr ruby_interpreter; + std::auto_ptr python_interpreter; + +#if defined(HAVE_QT) + // install the version strings lay::Version::set_exe_name (prg_exe_name); lay::Version::set_name (prg_name); @@ -349,12 +367,15 @@ main_cont (int &argc, char **argv) subversion += prg_rev; lay::Version::set_subversion (subversion.c_str ()); +#endif + int result = 0; ut::TestConsole console (stdout); try { +#if defined(HAVE_QT) pya::PythonInterpreter::initialize (); gsi::initialize_external (); @@ -372,35 +393,60 @@ main_cont (int &argc, char **argv) QTextCodec::setCodecForTr (QTextCodec::codecForName ("utf8")); #endif +#else + + // initialize the modules (load their plugins from the paths) + db::init (); + + // initialize the GSI class system (Variant binding, Expression support) + // We have to do this now since plugins may register GSI classes and before the + // ruby interpreter, because it depends on a proper class system. + gsi::initialize (); + + // initialize the tl::Expression subsystem with GSI-bound classes + gsi::initialize_expressions (); + + // instantiate the interpreters + + ruby_interpreter.reset (new rba::RubyInterpreter ()); + ruby_interpreter->push_console (&console); + + python_interpreter.reset (new pya::PythonInterpreter ()); + python_interpreter->push_console (&console); + +#endif + // Search and initialize plugin unit tests - QStringList name_filters; - name_filters << QString::fromUtf8 ("*.ut"); + std::string inst_dir = tl::get_inst_path (); + std::vector inst_modules = tl::dir_entries (inst_dir, true, false); + std::sort (inst_modules.begin (), inst_modules.end ()); - QDir inst_dir (tl::to_qstring (lay::get_inst_path ())); - QStringList inst_modules = inst_dir.entryList (name_filters); - inst_modules.sort (); + tl::GlobPattern pat ("*.ut"); - for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { + for (std::vector::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) { - QFileInfo ut_file (inst_dir.path (), *im); - if (ut_file.exists () && ut_file.isReadable ()) { + if (! pat.match (*im)) { + continue; + } - std::string pp = tl::to_string (ut_file.absoluteFilePath ()); - tl::log << "Loading unit tests " << pp; + std::string ut_file = tl::absolute_file_path (tl::combine_path (inst_dir, *im)); + if (tl::file_exists (ut_file)) { + + tl::log << "Loading unit tests " << ut_file; // NOTE: since we are using a different suffix ("*.ut"), we can't use QLibrary. #ifdef _WIN32 // there is no "dlopen" on mingw, so we need to emulate it. - HINSTANCE handle = LoadLibraryW ((const wchar_t *) tl::to_qstring (pp).constData ()); + HINSTANCE handle = LoadLibraryW (tl::to_wstring (ut_file).c_str ()); if (! handle) { - throw tl::Exception (tl::sprintf ("Unable to load plugin tests: %s with error message: %s", pp.c_str (), GetLastError ())); + throw tl::Exception (tl::sprintf ("Unable to load plugin tests: %s with error message: %s", ut_file.c_str (), GetLastError ())); } #else void *handle; - handle = dlopen (tl::string_to_system (pp).c_str (), RTLD_LAZY); + handle = dlopen (tl::string_to_system (ut_file).c_str (), RTLD_LAZY); if (! handle) { - throw tl::Exception (tl::sprintf ("Unable to load plugin tests: %s", pp.c_str ())); + throw tl::Exception (tl::sprintf ("Unable to load plugin tests: %s", ut_file.c_str ())); } #endif @@ -486,7 +532,7 @@ main_cont (int &argc, char **argv) ut::noctrl << "Entering KLayout test suite"; ut::noctrl << "TESTSRC=" << tl::testsrc (); - ut::noctrl << "TESTTMP=" << tl::to_string (QDir (tl::to_qstring (tl::testtmp ())).absolutePath ()); + ut::noctrl << "TESTTMP=" << tl::absolute_file_path (tl::testtmp ()); const std::vector *selected_tests = 0; std::vector subset; @@ -500,15 +546,19 @@ main_cont (int &argc, char **argv) bool exclude = false; for (std::vector::const_iterator m = exclude_test_list.begin (); m != exclude_test_list.end () && !exclude; ++m) { - QRegExp re (tl::to_qstring (*m), Qt::CaseInsensitive, QRegExp::Wildcard); - if (re.indexIn (tl::to_qstring ((*i)->name ())) == 0) { + tl::GlobPattern re (*m); + re.set_case_sensitive (false); + re.set_header_match (true); + if (re.match ((*i)->name ())) { exclude = true; } } for (std::vector::const_iterator m = test_list.begin (); !exclude && m != test_list.end (); ++m) { - QRegExp re (tl::to_qstring (*m), Qt::CaseInsensitive, QRegExp::Wildcard); - if (re.indexIn (tl::to_qstring ((*i)->name ())) == 0) { + tl::GlobPattern re (*m); + re.set_case_sensitive (false); + re.set_header_match (true); + if (re.match ((*i)->name ())) { ut::noctrl << " " << (*i)->name (); subset.push_back (*i); break; @@ -521,7 +571,7 @@ main_cont (int &argc, char **argv) selected_tests = &tl::TestRegistrar::instance()->tests (); } - result = run_tests (*selected_tests, editable, non_editable, slow, repeat, app, gsi_coverage, class_names); + result = run_tests (*selected_tests, editable, non_editable, slow, repeat, gsi_coverage, class_names); ut::ctrl << ""; diff --git a/src/with_all_libs.pri b/src/with_all_libs.pri index 0d3c0ecea..b4f316b1d 100644 --- a/src/with_all_libs.pri +++ b/src/with_all_libs.pri @@ -1,13 +1,22 @@ -INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC $$LIB_INC $$RBA_INC $$PYA_INC $$VERSION_INC -DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC $$LIB_INC $$RBA_INC $$PYA_INC $$VERSION_INC +INCLUDEPATH += $$RBA_INC $$PYA_INC $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC $$LIB_INC $$VERSION_INC +DEPENDPATH += $$RBA_INC $$PYA_INC $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC $$LIB_INC $$VERSION_INC -LIBS += $$PYTHONLIBFILE $$RUBYLIBFILE -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_rdb -lklayout_lym -lklayout_laybasic -lklayout_lay -lklayout_ant -lklayout_img -lklayout_edt -lklayout_lib +LIBS += $$PYTHONLIBFILE $$RUBYLIBFILE -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_rdb -lklayout_lib -# Note: this accounts for UI-generated headers placed into the output folders in -# shadow builds: -INCLUDEPATH += $$DESTDIR/laybasic $$DESTDIR/lay $$DESTDIR/ext -DEPENDPATH += $$DESTDIR/laybasic $$DESTDIR/lay $$DESTDIR/ext +!equals(HAVE_QT, "0") { + + INCLUDEPATH += $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC + DEPENDPATH += $$LYM_INC $$LAYBASIC_INC $$LAY_INC $$ANT_INC $$IMG_INC $$EDT_INC + + LIBS += -L$$DESTDIR -lklayout_lym -lklayout_laybasic -lklayout_lay -lklayout_ant -lklayout_img -lklayout_edt + + # Note: this accounts for UI-generated headers placed into the output folders in + # shadow builds: + INCLUDEPATH += $$DESTDIR/laybasic $$DESTDIR/lay $$DESTDIR/ext + DEPENDPATH += $$DESTDIR/laybasic $$DESTDIR/lay $$DESTDIR/ext + +} equals(HAVE_QTBINDINGS, "1") { LIBS += -lklayout_qtbasic -lklayout_QtGui -lklayout_QtCore @@ -25,9 +34,11 @@ equals(HAVE_PYTHON, "1") { LIBS += -lklayout_pyastub } -equals(HAVE_RUBY, "1") { - # DRC is only available with Ruby - INCLUDEPATH += $$DRC_INC - DEPENDPATH += $$DRC_INC - LIBS += -lklayout_drc +!equals(HAVE_QT, "0") { + equals(HAVE_RUBY, "1") { + # DRC is only available with Ruby + INCLUDEPATH += $$DRC_INC + DEPENDPATH += $$DRC_INC + LIBS += -lklayout_drc + } }