diff --git a/.github/workflows/Build-multi-OS.yml b/.github/workflows/Build-multi-OS.yml index b90885af1..afd683861 100644 --- a/.github/workflows/Build-multi-OS.yml +++ b/.github/workflows/Build-multi-OS.yml @@ -38,7 +38,7 @@ jobs: cl: 17 build_type: Release build_root: build-imagingsuite - - os: ubuntu-latest + - os: ubuntu-22.04 c_compiler: gcc cpp_compiler: g++ gcc: 11 @@ -149,16 +149,38 @@ jobs: - name: Ammend shared libraries runpaths if: ${{ runner.os == 'Linux' }} - working-directory: build-imagingsuite/Release/lib + working-directory: build-imagingsuite/Release shell: bash - run: patchelf --set-rpath '$ORIGIN' *.so* + run: | + patchelf --set-rpath '$ORIGIN' lib/*.so* + patchelf --set-rpath '$ORIGIN:$ORIGIN/../../lib' PlugIns/BackProjectors/*.so* + patchelf --set-rpath '$ORIGIN:$ORIGIN/../../lib' PlugIns/Preprocessors/*.so* - name: Test id: tests working-directory: ${{ matrix.build_root }} + shell: bash #Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). #See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest --build-config ${{ matrix.build_type }} + # The seperation of module files into seperate folders breaks the ctest test discovery, copy temprarily to the root folder for testing + run: | + if [ "${RUNNER_OS}" == "Windows" ]; then + cp ./bin/Release/PlugIns/Preprocessors/* ./bin/Release/PlugIns/BackProjectors/* ./bin/Release/ + elif [ "${RUNNER_OS}" == "Linux" ]; then + cp ./PlugIns/Preprocessors/* ./PlugIns/BackProjectors/* ./lib/ + elif [ "${RUNNER_OS}" == "macOS" ]; then + cp ./lib/Preprocessors/* ./lib/BackProjectors/* ./lib/ + fi + + ctest --build-config ${{ matrix.build_type }} + + if [ "${RUNNER_OS}" == "Windows" ]; then + rm ./bin/Release/*Modules.dll ./bin/Release/*Projectors.dll + elif [ "${RUNNER_OS}" == "Linux" ]; then + rm lib/*Modules.so lib/*Projectors.so + elif [ "${RUNNER_OS}" == "macOS" ]; then + rm -r lib/*Modules.dylib lib/*Projectors.dylib lib/sse2neon + fi continue-on-error: true - name: Archive test results @@ -168,22 +190,33 @@ jobs: name: ${{runner.os}}-${{runner.arch}}-test-results path: ${{ matrix.build_root }}/Testing - - name: Compress artifact - shell: bash - working-directory: ${{ matrix.build_root }} - run: | - if [ "${RUNNER_OS}" == "Windows" ]; then - 7z a ../MuhRec-${{runner.os}}-${{runner.arch}}.zip "bin/Release/*" -xr!t*.exe -xr!muhreccli.exe -xr!verticalslicer.exe - elif [ "${RUNNER_OS}" == "Linux" ]; then - zip -r ../../MuhRec-${{runner.os}}-${{runner.arch}}.zip bin/* lib/* -x "bin/t*" -x "bin/verticalslicer" - elif [ "${RUNNER_OS}" == "macOS" -a "${RUNNER_ARCH}" == "X64" ]; then - zip -r ../../MuhRec-${{runner.os}}-${{runner.arch}}.zip lib/* *.app/* -x "lib/*.dylib" - elif [ "${RUNNER_OS}" == "macOS" -a "${RUNNER_ARCH}" == "ARM64" ]; then - zip -r ../../MuhRec-${{runner.os}}-${{runner.arch}}.zip lib/* *.app/* -x "lib/*.dylib" -x "lib/*.h" - fi + - name: Save build artifact Windows + if: ${{ runner.os == 'Windows' }} + uses: actions/upload-artifact@master + with: + name: MuhRec-${{runner.os}}-${{runner.arch}} + path: | + ${{ matrix.build_root }}/bin/Release/* + !${{ matrix.build_root }}/bin/Release/t*.exe + !${{ matrix.build_root }}/bin/Release/*.pyd - - name: Save build artifact + - name: Save build artifact Linux + if: ${{ runner.os == 'Linux' }} + uses: actions/upload-artifact@master + with: + name: MuhRec-${{runner.os}}-${{runner.arch}} + path: | + ${{ matrix.build_root }}/bin/* + !${{ matrix.build_root }}/bin/t* + ${{ matrix.build_root }}/PlugIns/* + ${{ matrix.build_root }}/lib/* + !${{ matrix.build_root }}/lib/*cpython* + ${{ matrix.build_root }}/resources/* + + - name: Save build artifact MacOS + if: ${{ runner.os == 'macOS' }} uses: actions/upload-artifact@master with: name: MuhRec-${{runner.os}}-${{runner.arch}} - path: "${{ github.workspace }}/MuhRec*.zip" + path: | + ${{ matrix.build_root }}/*.app/* \ No newline at end of file diff --git a/.github/workflows/Build-wheels.yml b/.github/workflows/Build-wheels.yml index f7476481f..d40b9fa43 100644 --- a/.github/workflows/Build-wheels.yml +++ b/.github/workflows/Build-wheels.yml @@ -32,8 +32,8 @@ jobs: # 4. -# ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/UnitTests/python/testBindAverageImage.py -# ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/UnitTests/python/testBindAverageImage.py -#) -# -#add_test( -# NAME -# testBindPolynomialCorrection -# COMMAND -# ${CMAKE_COMMAND} -E env IMAGALG_MODULE_PATH=$ -# ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/UnitTests/python/testBindPolynomialCorrection.py -#) +set_target_properties(InspectorModules StdPreprocModules + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${PREPROCESSOR_MODULES_DIRECTORY} + RUNTIME_OUTPUT_DIRECTORY ${PREPROCESSOR_MODULES_DIRECTORY} +) + +set_target_properties(FDKBackProjectors StdBackProjectors + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${PROJECTOR_MODULES_DIRECTORY} + RUNTIME_OUTPUT_DIRECTORY ${PROJECTOR_MODULES_DIRECTORY} +) \ No newline at end of file diff --git a/GUI/qt/QtModuleConfigure/AddModuleDialog.cpp b/GUI/qt/QtModuleConfigure/AddModuleDialog.cpp index 9e05ec4ce..8e403d184 100644 --- a/GUI/qt/QtModuleConfigure/AddModuleDialog.cpp +++ b/GUI/qt/QtModuleConfigure/AddModuleDialog.cpp @@ -34,7 +34,8 @@ AddModuleDialog::AddModuleDialog(QWidget * parent) : m_Button_Cancel("Cancel"), m_sApplication("muhrec"), m_sApplicationPath(""), - m_ModuleConfig("") + m_sPreprocessorsPath(""), + m_ModuleConfig("","") { setWindowTitle(tr("Add a module")); setLayout(&m_Dlg_layout); @@ -60,9 +61,26 @@ AddModuleDialog::AddModuleDialog(QWidget * parent) : connect(&m_Button_OK,SIGNAL(clicked()),this,SLOT(accept())); connect(&m_Button_Cancel,SIGNAL(clicked()),this,SLOT(reject())); connect(&m_Button_Browse,SIGNAL(clicked()),this,SLOT(on_change_objectfile())); + + m_sApplicationPath = QCoreApplication::applicationDirPath().toStdString(); + kipl::strings::filenames::CheckPathSlashes(m_sApplicationPath,true); + +#if defined(Q_OS_WIN) + m_sPreprocessorsPath = m_sApplicationPath+"PlugIns\\Preprocessors\\"; +#elif defined(Q_OS_MAC) + m_sPreprocessorsPath = m_sApplicationPath+"../PlugIns/Preprocessors/"; +#elif defined(Q_OS_LINUX) + m_sPreprocessorsPath = m_sApplicationPath+"../PlugIns/Preprocessors/"; +#endif + + kipl::strings::filenames::CheckPathSlashes(m_sPreprocessorsPath,true); + } -int AddModuleDialog::configure(std::string application, std::string defaultsource, std::string application_path) +int AddModuleDialog::configure( const std::string &application, + const std::string &defaultsource, + const std::string &application_path, + const std::string &sCategory) { m_sApplication = application; m_sApplicationPath = application_path; @@ -74,10 +92,9 @@ int AddModuleDialog::configure(std::string application, std::string defaultsourc int AddModuleDialog::exec() { - QString appPath = QCoreApplication::applicationDirPath(); std::ostringstream msg; - msg<<"appPath "< > modulelist; std::string m_sApplication; std::string m_sApplicationPath; + std::string m_sPreprocessorsPath; std::string m_sDefaultModuleSource; ModuleConfig m_ModuleConfig; }; diff --git a/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.cpp b/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.cpp index 29a357f19..5b8bbd0e8 100644 --- a/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.cpp +++ b/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.cpp @@ -21,6 +21,7 @@ ModuleChainConfiguratorWidget::ModuleChainConfiguratorWidget(QWidget *parent) : m_pCurrentModule(nullptr), m_sApplication("muhrec"), m_sApplicationPath(""), + m_sCategory(""), m_pApplication(nullptr), m_pConfigurator(nullptr) { @@ -42,10 +43,14 @@ ModuleChainConfiguratorWidget::ModuleChainConfiguratorWidget(QWidget *parent) : show(); } -void ModuleChainConfiguratorWidget::configure(std::string application, std::string applicationpath, ModuleConfigurator *pConfigurator) +void ModuleChainConfiguratorWidget::configure(const std::string &application, + const std::string &applicationpath, + const std::string &category, + ModuleConfigurator *pConfigurator) { m_sApplication = application; m_sApplicationPath = applicationpath; + m_sCategory = category; m_pConfigurator = pConfigurator; } @@ -65,7 +70,7 @@ void ModuleChainConfiguratorWidget::on_Button_ModuleAdd() AddModuleDialog dlg(this); - dlg.configure(m_sApplication,m_sDefaultModuleSource,m_sApplicationPath); + dlg.configure(m_sApplication,m_sDefaultModuleSource,m_sApplicationPath,m_sCategory); if (dlg.exec()==QDialog::Accepted) { auto mcfg=dlg.GetModuleConfig(); diff --git a/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.h b/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.h index 090d32e51..19a2e29cd 100644 --- a/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.h +++ b/GUI/qt/QtModuleConfigure/modulechainconfiguratorwidget.h @@ -30,7 +30,7 @@ class QTMODULECONFIGURESHARED_EXPORT ModuleChainConfiguratorWidget : public QWid kipl::logging::Logger logger; public: explicit ModuleChainConfiguratorWidget(QWidget *parent = nullptr); - void configure(std::string application, std::string applicationpath="", ModuleConfigurator *pConfigurator=nullptr); + void configure(const std::string &application, const std::string &applicationpath="", const std::string &category="", ModuleConfigurator *pConfigurator=nullptr); void SetApplicationObject(ApplicationBase * app ); void SetDefaultModuleSource(std::string file); std::vector GetModules(); @@ -76,6 +76,7 @@ public slots: std::string m_sApplication; std::string m_sApplicationPath; + std::string m_sCategory; std::string m_sDefaultModuleSource; ApplicationBase * m_pApplication ; ModuleConfigurator * m_pConfigurator; diff --git a/GUI/qt/QtModuleConfigure/singlemoduleconfiguratorwidget.cpp b/GUI/qt/QtModuleConfigure/singlemoduleconfiguratorwidget.cpp index def0aae66..9331bc309 100644 --- a/GUI/qt/QtModuleConfigure/singlemoduleconfiguratorwidget.cpp +++ b/GUI/qt/QtModuleConfigure/singlemoduleconfiguratorwidget.cpp @@ -30,7 +30,7 @@ typedef void * HINSTANCE; SingleModuleConfiguratorWidget::SingleModuleConfiguratorWidget(QWidget *parent) : QFrame(parent), logger("SingleModuleConfiguratorWidget"), - m_ModuleConfig("") + m_ModuleConfig("","") { this->setFrameStyle(6); this->setLayout(&m_LayoutMain); @@ -50,16 +50,21 @@ SingleModuleConfiguratorWidget::SingleModuleConfiguratorWidget(QWidget *parent) } -void SingleModuleConfiguratorWidget::Configure(std::string sApplicationName, std::string sDefaultModuleSource, std::string sApplicationPath) +void SingleModuleConfiguratorWidget::Configure( const std::string &sApplicationName, + const std::string &sDefaultModuleSource, + const std::string &sApplicationPath, + const std::string &sCategory) { + m_sApplication = sApplicationName; m_sApplicationPath = sApplicationPath; + m_sCategory = sCategory; m_sDefaultModuleSource = sDefaultModuleSource; m_ModuleConfig.m_sSharedObject = sDefaultModuleSource; - m_ModuleConfig.setAppPath(sApplicationPath); + m_ModuleConfig.setAppPath(sApplicationPath,m_sCategory); } -void SingleModuleConfiguratorWidget::setDescriptionLabel(QString lbl) +void SingleModuleConfiguratorWidget::setDescriptionLabel(const QString &lbl) { m_LabelDescription.setText(lbl); } @@ -94,7 +99,7 @@ void SingleModuleConfiguratorWidget::SetDescription(QString name) void SingleModuleConfiguratorWidget::on_ButtonConfigure_Clicked() { - SingleModuleSettingsDialog dlg(m_sApplication, m_sApplicationPath,m_sDefaultModuleSource,this); + SingleModuleSettingsDialog dlg(m_sApplication, m_sApplicationPath, m_sCategory,m_sDefaultModuleSource,this); int res=dlg.exec(m_ModuleConfig); @@ -105,345 +110,353 @@ void SingleModuleConfiguratorWidget::on_ButtonConfigure_Clicked() } } -namespace oldGUI { -SingleModuleSettingsDialog::SingleModuleSettingsDialog(const std::string &sApplicationName, - const std::string &sApplicationPath, - const std::string &sDefaultModuleSource, - QWidget *parent) : - QDialog(parent), - logger("SingleModuleSettingsDialog"), - m_sApplication(sApplicationName), - m_sApplicationPath(sApplicationPath), - m_sDefaultModuleSource(sDefaultModuleSource), - m_ModuleConfig("") -{ - BuildDialog(); - connect(&m_ButtonBrowse,SIGNAL(clicked()),this,SLOT(on_ButtonBrowse_Clicked())); - connect(&m_Buttons,SIGNAL(clicked(QAbstractButton*)),this,SLOT(on_ButtonBox_Clicked(QAbstractButton*))); - connect(&m_ComboModules,SIGNAL(currentIndexChanged(QString)),this,SLOT(on_ComboBox_Changed(QString))); - show(); - -} - -int SingleModuleSettingsDialog::exec(ModuleConfig &config) -{ - std::ostringstream msg; - m_ModuleConfig=config; - m_ModuleConfig.setAppPath(QCoreApplication::applicationDirPath().toStdString()); - - QDir dir; - if (dir.exists(QString::fromStdString(m_ModuleConfig.m_sSharedObject))) - { - UpdateModuleCombobox(QString::fromStdString(m_ModuleConfig.m_sSharedObject),false); - msg<<"Index for "<property("ActionRole").toInt(); - QString s_Value=button->text(); - msg<<"Got NoButton: "<text().toStdString(); - - logger(kipl::logging::Logger::LogMessage,msg.str()); - - if (s_Value.toLower()=="add") - { - logger(kipl::logging::Logger::LogMessage,"Add parameter"); - } - - if (s_Value.toLower()=="delete") - { - logger(kipl::logging::Logger::LogMessage,"Delete parameter"); - } - break; - } - - case QDialogButtonBox::Apply: break; - case QDialogButtonBox::Reset: break; - case QDialogButtonBox::Save: break; - case QDialogButtonBox::SaveAll: break; - case QDialogButtonBox::Open: break; - case QDialogButtonBox::Close: break; - case QDialogButtonBox::Discard: break; - case QDialogButtonBox::Ignore: break; - case QDialogButtonBox::No: break; - case QDialogButtonBox::YesToAll: break; - case QDialogButtonBox::NoToAll: break; - case QDialogButtonBox::Yes: break; - case QDialogButtonBox::Retry: break; - case QDialogButtonBox::Abort: break; - case QDialogButtonBox::Help: break; - case QDialogButtonBox::RestoreDefaults: break; - } - -} - -void SingleModuleSettingsDialog::on_ButtonBrowse_Clicked() -{ - logger(kipl::logging::Logger::LogMessage,"browse"); - - QString fileName; - #ifdef Q_OS_WIN - QString appPath = QCoreApplication::applicationDirPath()+"\\"; - fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dll)")); - #else - QString appPath = QCoreApplication::applicationDirPath()+"/../Frameworks/"; - fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dylib | *.so)")); - #endif - logger(kipl::logging::Logger::LogMessage,appPath.toStdString()); - - if ( fileName.isNull() ) - { - logger(kipl::logging::Logger::LogError,"File selection was cancelled"); - return; - } - - if ( fileName.isEmpty() ) - { - logger(kipl::logging::Logger::LogError,"No file selected"); - return; - } - - logger(kipl::logging::Logger::LogMessage,fileName.toStdString()); - - if (fileName.toStdString() == m_ModuleConfig.m_sSharedObject ) - { - logger(kipl::logging::Logger::LogMessage,"The same library file was selected."); - return; - } - - if (UpdateModuleCombobox(fileName)==0) - m_ModuleConfig.m_sSharedObject=fileName.toStdString(); -} - -void SingleModuleSettingsDialog::BuildDialog() -{ - this->setLayout(&m_LayoutMain); - this->setWindowTitle("Select and configure module"); - m_LayoutMain.addLayout(&m_LayoutModule); - m_LayoutModule.addWidget(&m_LabelModuleName); - m_LabelModuleName.setText(tr("Module")); - m_LabelModuleName.setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Preferred); - m_LayoutModule.addWidget(&m_ComboModules); - m_LayoutModule.addWidget(&m_ButtonBrowse); - m_ButtonBrowse.setText(tr("Browse")); - m_ButtonBrowse.setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Preferred); - m_LayoutMain.addWidget(&m_ParameterListView); - m_ParameterListView.setColumnCount(2); - m_ParameterListView.setHeaderLabels(QStringList()< > SingleModuleSettingsDialog::GetModuleList(std::string filename) -{ - std::ostringstream msg; - HINSTANCE hinstLib; -#ifdef _MSC_VER - std::wstring so(filename.begin(),filename.end()); - - hinstLib = LoadLibraryW(so.c_str()); -#else - hinstLib = dlopen(filename.c_str(), RTLD_LAZY); -#endif - - if (hinstLib != nullptr) - { - MODULELIST fnGetModuleList; -#ifdef _MSC_VER - fnGetModuleList = reinterpret_cast(GetProcAddress(hinstLib, "GetModuleList")); -#else - fnGetModuleList = reinterpret_cast(dlsym(hinstLib, "GetModuleList")); -#endif - msg.str(""); - msg<<"Got functions from "< SingleModuleSettingsDialog::GetParameterList() -{ - std::map parlist; - - for( int i = 0; i < m_ParameterListView.topLevelItemCount(); ++i ) - { - QTreeWidgetItem *item = m_ParameterListView.topLevelItem( i ); - parlist[item->text(0).toStdString()]=item->text(1).toStdString(); - } - - return parlist; -} - -void SingleModuleSettingsDialog::UpdateCurrentModuleParameters() -{ - m_ParameterListView.clear(); - QTreeWidgetItem *parent = m_ParameterListView.invisibleRootItem(); - QTreeWidgetItem *item = nullptr; - - std::ostringstream msg; - msg<<"Updating parameter list for "<width()/2); - if (!m_ModuleConfig.m_sModule.empty()) - { -// std::map::iterator parameters; - - for (const auto & parameters : m_ModuleConfig.parameters) - { - item=new QTreeWidgetItem(parent); - item->setFlags(item->flags() | Qt::ItemIsEditable); - item->setText(0,QString::fromStdString(parameters.first)); - item->setText(1,QString::fromStdString(parameters.second)); - msg.str(""); - msg<property("ActionRole").toInt(); +// QString s_Value=button->text(); +// msg<<"Got NoButton: "<text().toStdString(); + +// logger(kipl::logging::Logger::LogMessage,msg.str()); + +// if (s_Value.toLower()=="add") +// { +// logger(kipl::logging::Logger::LogMessage,"Add parameter"); +// } + +// if (s_Value.toLower()=="delete") +// { +// logger(kipl::logging::Logger::LogMessage,"Delete parameter"); +// } +// break; +// } + +// case QDialogButtonBox::Apply: break; +// case QDialogButtonBox::Reset: break; +// case QDialogButtonBox::Save: break; +// case QDialogButtonBox::SaveAll: break; +// case QDialogButtonBox::Open: break; +// case QDialogButtonBox::Close: break; +// case QDialogButtonBox::Discard: break; +// case QDialogButtonBox::Ignore: break; +// case QDialogButtonBox::No: break; +// case QDialogButtonBox::YesToAll: break; +// case QDialogButtonBox::NoToAll: break; +// case QDialogButtonBox::Yes: break; +// case QDialogButtonBox::Retry: break; +// case QDialogButtonBox::Abort: break; +// case QDialogButtonBox::Help: break; +// case QDialogButtonBox::RestoreDefaults: break; +// } + +// } + +// void SingleModuleSettingsDialog::on_ButtonBrowse_Clicked() +// { +// logger(kipl::logging::Logger::LogMessage,"browse"); + +// QString appPath = QCoreApplication::applicationDirPath(); +// QString fileName; + +// #if defined(Q_OS_WIN) +// appPath+="/Preprocessors"; +// fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dll)")); +// #elif defined(Q_OS_MAC) +// appPath+="/../Preprocessors"; +// fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dylib)")); +// #elif defined(Q_OS_LINUX) +// appPath+="/../Preprocessors"; +// fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.so)")); +// #endif + +// logger(kipl::logging::Logger::LogMessage,appPath.toStdString()); + +// if ( fileName.isNull() ) +// { +// logger(kipl::logging::Logger::LogError,"File selection was cancelled"); +// return; +// } + +// if ( fileName.isEmpty() ) +// { +// logger(kipl::logging::Logger::LogError,"No file selected"); +// return; +// } + +// logger(kipl::logging::Logger::LogMessage,fileName.toStdString()); + +// if (fileName.toStdString() == m_ModuleConfig.m_sSharedObject ) +// { +// logger(kipl::logging::Logger::LogMessage,"The same library file was selected."); +// return; +// } + +// if (UpdateModuleCombobox(fileName)==0) +// m_ModuleConfig.m_sSharedObject=fileName.toStdString(); +// } + +// void SingleModuleSettingsDialog::BuildDialog() +// { +// this->setLayout(&m_LayoutMain); +// this->setWindowTitle("Select and configure module"); +// m_LayoutMain.addLayout(&m_LayoutModule); +// m_LayoutModule.addWidget(&m_LabelModuleName); +// m_LabelModuleName.setText(tr("Module")); +// m_LabelModuleName.setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Preferred); +// m_LayoutModule.addWidget(&m_ComboModules); +// m_LayoutModule.addWidget(&m_ButtonBrowse); +// m_ButtonBrowse.setText(tr("Browse")); +// m_ButtonBrowse.setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Preferred); +// m_LayoutMain.addWidget(&m_ParameterListView); +// m_ParameterListView.setColumnCount(2); +// m_ParameterListView.setHeaderLabels(QStringList()< > SingleModuleSettingsDialog::GetModuleList(std::string filename) +// { +// std::ostringstream msg; +// HINSTANCE hinstLib; +// #ifdef _MSC_VER +// std::wstring so(filename.begin(),filename.end()); + +// hinstLib = LoadLibraryW(so.c_str()); +// #else +// hinstLib = dlopen(filename.c_str(), RTLD_LAZY); +// #endif + +// if (hinstLib != nullptr) +// { +// MODULELIST fnGetModuleList; +// #ifdef _MSC_VER +// fnGetModuleList = reinterpret_cast(GetProcAddress(hinstLib, "GetModuleList")); +// #else +// fnGetModuleList = reinterpret_cast(dlsym(hinstLib, "GetModuleList")); +// #endif +// msg.str(""); +// msg<<"Got functions from "< SingleModuleSettingsDialog::GetParameterList() +// { +// std::map parlist; + +// for( int i = 0; i < m_ParameterListView.topLevelItemCount(); ++i ) +// { +// QTreeWidgetItem *item = m_ParameterListView.topLevelItem( i ); +// parlist[item->text(0).toStdString()]=item->text(1).toStdString(); +// } + +// return parlist; +// } + +// void SingleModuleSettingsDialog::UpdateCurrentModuleParameters() +// { +// m_ParameterListView.clear(); +// QTreeWidgetItem *parent = m_ParameterListView.invisibleRootItem(); +// QTreeWidgetItem *item = nullptr; + +// std::ostringstream msg; +// msg<<"Updating parameter list for "<width()/2); +// if (!m_ModuleConfig.m_sModule.empty()) +// { +// // std::map::iterator parameters; + +// for (const auto & parameters : m_ModuleConfig.parameters) +// { +// item=new QTreeWidgetItem(parent); +// item->setFlags(item->flags() | Qt::ItemIsEditable); +// item->setText(0,QString::fromStdString(parameters.first)); +// item->setText(1,QString::fromStdString(parameters.second)); +// msg.str(""); +// msg< > GetModuleList(std::string filename); - std::map GetParameterList(); - void UpdateCurrentModuleParameters(); - - - std::string m_sApplication; - std::string m_sApplicationPath; - std::string m_sDefaultModuleSource; - QVBoxLayout m_LayoutMain; - QHBoxLayout m_LayoutModule; - QLabel m_LabelModuleName; - QComboBox m_ComboModules; - QPushButton m_ButtonBrowse; - - QTreeWidget m_ParameterListView; - QDialogButtonBox m_Buttons; - QPushButton m_ButtonOK; - QPushButton m_ButtonCancel; - QPushButton m_ButtonAdd; - QPushButton m_ButtonDelete; - - ModuleConfig m_ModuleConfig; - std::map > m_ModuleList; - - -}; -} +// namespace oldGUI { +// class QTMODULECONFIGURESHARED_EXPORT SingleModuleSettingsDialog : QDialog +// { +// Q_OBJECT +// kipl::logging::Logger logger; +// public: +// explicit SingleModuleSettingsDialog(const std::string &sApplicationName, const std::string &sApplicationPath, const std::string &sCategory, const std::string & sDefaultModuleSource ,QWidget *parent); + +// virtual int exec(ModuleConfig &config); +// ModuleConfig getModule(); + +// public slots: +// virtual void on_ButtonBrowse_Clicked(); +// virtual void on_ButtonBox_Clicked(QAbstractButton *button); +// virtual void on_ComboBox_Changed(QString value); + +// private: +// virtual int exec(); +// void BuildDialog(); +// int UpdateModuleCombobox(QString fname, bool bSetFirstIndex=true); +// std::map > GetModuleList(std::string filename); +// std::map GetParameterList(); +// void UpdateCurrentModuleParameters(); + + +// std::string m_sApplication; +// std::string m_sApplicationPath; +// std::string m_sCategory; +// std::string m_sDefaultModuleSource; +// QVBoxLayout m_LayoutMain; +// QHBoxLayout m_LayoutModule; +// QLabel m_LabelModuleName; +// QComboBox m_ComboModules; +// QPushButton m_ButtonBrowse; + +// QTreeWidget m_ParameterListView; +// QDialogButtonBox m_Buttons; +// QPushButton m_ButtonOK; +// QPushButton m_ButtonCancel; +// QPushButton m_ButtonAdd; +// QPushButton m_ButtonDelete; + +// ModuleConfig m_ModuleConfig; +// std::map > m_ModuleList; + + +// }; +// } #endif // SINGLEMODULECONFIGURATORWIDGET_H diff --git a/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.cpp b/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.cpp index b820f8541..0bb3f95ff 100644 --- a/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.cpp +++ b/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.cpp @@ -24,6 +24,7 @@ typedef void * HINSTANCE; SingleModuleSettingsDialog::SingleModuleSettingsDialog(const std::string &sApplicationName, const std::string &sApplicationPath, + const std::string &sCategory, const std::string & sDefaultModuleSource, QWidget *parent) : QDialog(parent), @@ -31,8 +32,9 @@ SingleModuleSettingsDialog::SingleModuleSettingsDialog(const std::string &sAppli ui(new Ui::SingleModuleSettingsDialog), m_sApplication(sApplicationName), m_sApplicationPath(sApplicationPath), + m_sCategory(sCategory), m_sDefaultModuleSource(sDefaultModuleSource), - m_ModuleConfig("") + m_ModuleConfig("","") { ui->setupUi(this); } @@ -46,7 +48,7 @@ int SingleModuleSettingsDialog::exec(ModuleConfig &config) { std::ostringstream msg; m_ModuleConfig=config; - m_ModuleConfig.setAppPath(QCoreApplication::applicationDirPath().toStdString()); + m_ModuleConfig.setAppPath(QCoreApplication::applicationDirPath().toStdString(),m_sCategory); QDir dir; if (dir.exists(QString::fromStdString(m_ModuleConfig.m_sSharedObject))) @@ -255,13 +257,17 @@ void SingleModuleSettingsDialog::on_pushButton_Browse_clicked() { logger.message("Browse"); + QString appPath = QCoreApplication::applicationDirPath(); QString fileName; - #ifdef Q_OS_WIN - QString appPath = QCoreApplication::applicationDirPath()+"\\"; + #if defined(Q_OS_WIN) + appPath += "/PlugIns/BackProjectors"; fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dll)")); - #else - QString appPath = QCoreApplication::applicationDirPath()+"/../Frameworks/"; - fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dylib | *.so)")); + #elif defined(Q_OS_MAC) + appPath +="/../PlugIns/BackProjectors/"; + fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.dylib)")); + #elif defined(Q_OS_LINUX) + appPath +="/../PlugIns/BackProjectors/"; + fileName = QFileDialog::getOpenFileName(this,tr("Open module library"),appPath,tr("libs (*.so)")); #endif logger.message(appPath.toStdString()); diff --git a/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.h b/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.h index 187dd1d90..f2bc4e847 100644 --- a/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.h +++ b/GUI/qt/QtModuleConfigure/singlemodulesettingsdialog.h @@ -24,6 +24,7 @@ class QTMODULECONFIGURESHARED_EXPORT SingleModuleSettingsDialog : public QDialog public: explicit SingleModuleSettingsDialog(const std::string &sApplicationName, const std::string &sApplicationPath, + const std::string &sCategory, const std::string & sDefaultModuleSource, QWidget *parent = nullptr); @@ -51,6 +52,7 @@ private slots: std::string m_sApplication; std::string m_sApplicationPath; + std::string m_sCategory; std::string m_sDefaultModuleSource; ModuleConfig m_ModuleConfig; diff --git a/applications/muhrec/src/muhrecmainwindow.cpp b/applications/muhrec/src/muhrecmainwindow.cpp index 33fd5b8b8..2bbc43e08 100644 --- a/applications/muhrec/src/muhrecmainwindow.cpp +++ b/applications/muhrec/src/muhrecmainwindow.cpp @@ -63,6 +63,8 @@ MuhRecMainWindow::MuhRecMainWindow(QApplication *app, QWidget *parent) : m_nCurrentPage(0), m_nRequiredMemory(0), m_sApplicationPath(app->applicationDirPath().toStdString()), + m_sPreprocessorsPath(""), + m_sBackProjectorsPath(""), m_sHomePath(QDir::homePath().toStdString()), m_sConfigFilename("noname.xml"), m_sPreviewMask(""), @@ -93,45 +95,43 @@ MuhRecMainWindow::MuhRecMainWindow(QApplication *app, QWidget *parent) : dir.mkdir(QString::fromStdString(m_sConfigPath)); } - msg.str(""); - msg<<"ApplicationPath = "<ConfiguratorBackProj->Configure("muhrecbp",defaultmodules,m_sApplicationPath); - -#ifdef Q_OS_WIN - defaultmodules=m_sApplicationPath+"\\StdPreprocModules.dll"; -#else - #ifdef Q_OS_MAC - defaultmodules = m_sApplicationPath+"../Frameworks/libStdPreprocModules.dylib"; - #else - //defaultmodules = m_sApplicationPath+"../Frameworks/libStdPreprocModules.so"; - defaultmodules = m_sApplicationPath+"../lib/libstdPreprocModules.so"; - #endif + std::string defaultpreprocessors; + std::string defaultprojectors; +#if defined(Q_OS_WIN) + m_sPreprocessorsPath = m_sApplicationPath+"PlugIns\\Preprocessors\\"; + m_sBackProjectorsPath = m_sApplicationPath+"PlugIns\\BackProjectors\\"; + defaultpreprocessors=m_sPreprocessorsPath+"StdPreprocModules.dll"; + defaultprojectors=m_sBackProjectorsPath+"StdBackProjectors.dll"; +#elif defined(Q_OS_MAC) + m_sPreprocessorsPath = m_sApplicationPath+"../PlugIns/Preprocessors/"; + m_sBackProjectorsPath = m_sApplicationPath+"../PlugIns/BackProjectors/"; + defaultpreprocessors=m_sPreprocessorsPath+"libStdPreprocModules.dylib"; + defaultprojectors=m_sBackProjectorsPath+"libStdBackProjectors.dylib"; +#elif defined(Q_OS_LINUX) + m_sPreprocessorsPath = m_sApplicationPath+"../PlugIns/Preprocessors/"; + m_sBackProjectorsPath = m_sApplicationPath+"../PlugIns/BackProjectors/"; + defaultpreprocessors=m_sPreprocessorsPath+"libStdPreprocModules.so"; + defaultprojectors=m_sBackProjectorsPath+"libStdBackProjectors.so"; #endif - ui->moduleconfigurator->configure("muhrec",m_sApplicationPath,&m_ModuleConfigurator); - ui->moduleconfigurator->SetDefaultModuleSource(defaultmodules); - ui->moduleconfigurator->SetApplicationObject(this); + kipl::strings::filenames::CheckPathSlashes(m_sPreprocessorsPath,true); + kipl::strings::filenames::CheckPathSlashes(m_sBackProjectorsPath,true); + msg.str(""); + msg<<"ApplicationPath = "<moduleconfigurator->configure("muhrec", m_sApplicationPath, "Preprocessors", &m_ModuleConfigurator); + ui->moduleconfigurator->SetDefaultModuleSource(defaultpreprocessors); + ui->moduleconfigurator->SetApplicationObject(this); m_oldROI = {0,0,1,1}; @@ -643,10 +643,6 @@ void MuhRecMainWindow::LoadDefaults(bool checkCurrent) std::string defaultsname=m_sHomePath+".imagingtools/CurrentRecon.xml"; kipl::strings::filenames::CheckPathSlashes(defaultsname,false); - - std::string sModulePath=m_sApplicationPath; - kipl::strings::filenames::CheckPathSlashes(sModulePath,true); - msg.str(""); msg<<"default name is "< 9: - shutil.copytree( - os.path.join(self.source_folder,"applications","muhrec","Resources"), - dst, - dirs_exist_ok=True, - ) - else: - shutil.copytree( - os.path.join(self.source_folder,"applications","muhrec","Resources"), - dst - ) + shutil.copytree( + os.path.join(self.source_folder,"applications","muhrec","Resources"), + dst, + dirs_exist_ok=True, + ) def build(self): cmake = CMake(self) cmake.configure() cmake.build() if self.settings.os == "Macos": - copy(self, "*.dylib", self.lib_folder, self.framework_folder_MuhRec, excludes='*cpython*') - copy(self, "*.dylib", self.lib_folder, self.framework_folder_imageviewer, excludes='*cpython*') + # Copy to both MuhRec and ImageViewer app bundles + for framework_folder in [self.framework_folder_MuhRec, self.framework_folder_imageviewer]: + copy(self, "*.dylib", self.lib_folder, framework_folder, excludes=['*cpython*', 'BackProjectors', 'Preprocessors']) + # Copy plugin dylibs to the PlugIns folder in the app bundles + for plugin_type in ["Preprocessors", "BackProjectors"]: + shutil.copytree( + os.path.join(self.lib_folder, plugin_type), + os.path.join(framework_folder, "..", "PlugIns", plugin_type), + dirs_exist_ok=True, + ) diff --git a/core/modules/ModuleConfig/include/ModuleConfig.h b/core/modules/ModuleConfig/include/ModuleConfig.h index e524b63f3..d52a0b2a2 100644 --- a/core/modules/ModuleConfig/include/ModuleConfig.h +++ b/core/modules/ModuleConfig/include/ModuleConfig.h @@ -23,7 +23,7 @@ class MODULECONFIGSHARED_EXPORT ModuleConfig kipl::logging::Logger logger; ///< Logging for the Module config objects public: - ModuleConfig(const std::string &modulePath); ///< Default constructor + ModuleConfig(const std::string &modulePath, const std::string &sCategory); ///< Default constructor std::string m_sSharedObject; ///< File name of the shared object file containing the module std::string m_sModule; ///< Name of the module bool m_bActive; @@ -40,12 +40,13 @@ class MODULECONFIGSHARED_EXPORT ModuleConfig /// Dumps the module parameters on the console. std::string PrintParameters(); - void setAppPath(const std::string &path); + void setAppPath(const std::string &path, const std::string &category); std::string modulePath(); std::string moduleSummary(); protected: ModuleLibNameManger m_NameManager; + std::string m_CategoryName; }; diff --git a/core/modules/ModuleConfig/include/modulelibnamemanger.h b/core/modules/ModuleConfig/include/modulelibnamemanger.h index c5a2e0e56..32983a68c 100644 --- a/core/modules/ModuleConfig/include/modulelibnamemanger.h +++ b/core/modules/ModuleConfig/include/modulelibnamemanger.h @@ -10,17 +10,17 @@ class MODULECONFIGSHARED_EXPORT ModuleLibNameManger { kipl::logging::Logger logger; public: - ModuleLibNameManger(const std::string &path); - std::string generateLibName(const std::string &name, const kipl::base::eOperatingSystem &os); - std::string generateLibName(const std::string &name); + ModuleLibNameManger(const std::string &path, const std::string &category); + std::string generateLibName(const std::string &namem, const kipl::base::eOperatingSystem &os); + std::string generateLibName( const std::string &name); std::string stripLibName(const std::string &libPath, const kipl::base::eOperatingSystem &os); std::string stripLibName(const std::string &libPath); - void setAppPath(const std::string &path); + void setAppPath(const std::string &path, const std::string &category); private: std::string generateWindowsLibName(const std::string &name); - std::string generateMacOSLibName(const std::string &name); - std::string generateLinuxLibName(const std::string &name); + std::string generateMacOSLibName( const std::string &name); + std::string generateLinuxLibName( const std::string &name); std::string stripWindowsLibName(const std::string &path); std::string stripMacOSLibName(const std::string &path); @@ -29,6 +29,7 @@ class MODULECONFIGSHARED_EXPORT ModuleLibNameManger bool libInAppPath(const std::string & path, const std::string &appPath); std::string m_sApplicationPath; + std::string m_sCategoryName; }; diff --git a/core/modules/ModuleConfig/src/ModuleConfig.cpp b/core/modules/ModuleConfig/src/ModuleConfig.cpp index 6b82bbb95..7fac95a93 100644 --- a/core/modules/ModuleConfig/src/ModuleConfig.cpp +++ b/core/modules/ModuleConfig/src/ModuleConfig.cpp @@ -12,13 +12,13 @@ #include -ModuleConfig::ModuleConfig(const std::string &appPath) : +ModuleConfig::ModuleConfig(const std::string &sAppPath, const std::string &sCategory) : logger("ModuleConfig"), m_sSharedObject("NoObjectFile"), m_sModule("Empty"), m_bActive(true), m_bThreading(false), - m_NameManager(appPath) + m_NameManager(sAppPath, sCategory) { } @@ -136,9 +136,9 @@ std::string ModuleConfig::PrintParameters() return s.str(); } -void ModuleConfig::setAppPath(const std::string &path) +void ModuleConfig::setAppPath(const std::string &path, const std::string &category) { - m_NameManager.setAppPath(path); + m_NameManager.setAppPath(path,category); } std::string ModuleConfig::modulePath() diff --git a/core/modules/ModuleConfig/src/modulelibnamemanger.cpp b/core/modules/ModuleConfig/src/modulelibnamemanger.cpp index 052636c62..b235a1d15 100644 --- a/core/modules/ModuleConfig/src/modulelibnamemanger.cpp +++ b/core/modules/ModuleConfig/src/modulelibnamemanger.cpp @@ -4,14 +4,16 @@ #include #include -ModuleLibNameManger::ModuleLibNameManger(const std::string &path) : +ModuleLibNameManger::ModuleLibNameManger(const std::string &path, const std::string &category) : logger("ModuleLibNameManger"), - m_sApplicationPath(path) + m_sApplicationPath(path), + m_sCategoryName(category) { -// kipl::strings::filenames::CheckPathSlashes(m_sApplicationPath,true); + // kipl::strings::filenames::CheckPathSlashes(m_sApplicationPath,true); + // kipl::strings::filenames::CheckPathSlashes(m_sCategoryName,true); } -std::string ModuleLibNameManger::generateLibName(const std::string &name, const kipl::base::eOperatingSystem &os) +std::string ModuleLibNameManger::generateLibName(const std::string &name,const kipl::base::eOperatingSystem &os) { if (name.find_first_of("/\\")!=std::string::npos) return name; @@ -55,17 +57,20 @@ std::string ModuleLibNameManger::stripLibName(const std::string &libPath) return stripLibName(libPath,kipl::base::getOperatingSystem()); } -void ModuleLibNameManger::setAppPath(const std::string &path) +void ModuleLibNameManger::setAppPath(const std::string &path, const std::string &category) { m_sApplicationPath = path; kipl::strings::filenames::CheckPathSlashes(m_sApplicationPath,true); -} + + m_sCategoryName = category; + kipl::strings::filenames::CheckPathSlashes(m_sCategoryName,true); +} std::string ModuleLibNameManger::generateWindowsLibName(const std::string &name) { std::string fullName=m_sApplicationPath; - fullName = fullName+name+".dll"; + fullName = fullName+"PlugIns\\"+m_sCategoryName+"\\"+name+".dll"; return fullName; } @@ -74,7 +79,7 @@ std::string ModuleLibNameManger::generateMacOSLibName(const std::string &name) { std::string fullName=m_sApplicationPath.substr(0,m_sApplicationPath.size() - 6 - (*m_sApplicationPath.rbegin()=='/' ? 1 : 0)); - fullName = fullName+"/Frameworks/lib"+name+".dylib"; + fullName = fullName+"/PlugIns/"+m_sCategoryName+"/lib"+name+".dylib"; return fullName; } @@ -83,15 +88,16 @@ std::string ModuleLibNameManger::generateLinuxLibName(const std::string &name) { std::string fullName=m_sApplicationPath.substr(0,m_sApplicationPath.size() - 3 - (*m_sApplicationPath.rbegin()=='/' ? 1 : 0)); - fullName = fullName+"lib/lib"+name+".so"; + fullName = fullName+"PlugIns/"+m_sCategoryName+"/lib"+name+".so"; return fullName; } std::string ModuleLibNameManger::stripWindowsLibName(const std::string &path) { - if (!libInAppPath(path,m_sApplicationPath)) + if (!libInAppPath(path,m_sApplicationPath+"PlugIns\\"+m_sCategoryName)) { + logger.message(path+" is not in the plugin path"); return path; } std::string libName; @@ -103,12 +109,10 @@ std::string ModuleLibNameManger::stripWindowsLibName(const std::string &path) std::string ModuleLibNameManger::stripMacOSLibName(const std::string &path) { - std::ostringstream msg; - if (!libInAppPath(path,m_sApplicationPath.substr(0,m_sApplicationPath.size()-7)+"/Frameworks") && - !libInAppPath(path,m_sApplicationPath+"../Frameworks") ) + if (!libInAppPath(path,m_sApplicationPath.substr(0,m_sApplicationPath.size()-7)+"/PlugIns/"+m_sCategoryName) && + !libInAppPath(path,m_sApplicationPath+"../PlugIns/"+m_sCategoryName) ) { - msg << path.c_str()<<" is not in lib path"; - logger.verbose(msg.str()); + logger.message(path+" is not in the plugin path"); return path; } @@ -123,14 +127,10 @@ std::string ModuleLibNameManger::stripMacOSLibName(const std::string &path) std::string ModuleLibNameManger::stripLinuxLibName(const std::string &path) { - std::ostringstream msg; - - - if (!libInAppPath(path,m_sApplicationPath.substr(0,m_sApplicationPath.size()-4)+"/lib") && - !libInAppPath(path,m_sApplicationPath+"../lib/") ) + if (!libInAppPath(path,m_sApplicationPath.substr(0,m_sApplicationPath.size()-4)+"/PlugIns/"+m_sCategoryName) && + !libInAppPath(path,m_sApplicationPath+"../PlugIns/"+m_sCategoryName) ) { - msg << path.c_str()<<" is not in lib path"; - logger.verbose(msg.str()); + logger.message(path+" is not in the plugin path"); return path; } @@ -146,13 +146,13 @@ bool ModuleLibNameManger::libInAppPath(const std::string &path, const std::strin { if (path.size()::iterator it; for (auto & module : modules) { - module.setAppPath(m_sApplicationPath); + module.setAppPath(m_sApplicationPath,"Preprocessors"); str<\n"; @@ -514,7 +514,7 @@ void ReconConfig::ParseProcessChain(xmlTextReaderPtr reader) sValue="Empty"; sName=reinterpret_cast(name); if (sName=="module") { - ModuleConfig module(m_sApplicationPath); + ModuleConfig module(m_sApplicationPath, "Preprocessors"); module.ParseModule(reader); modules.push_back(module); } @@ -526,7 +526,7 @@ void ReconConfig::ParseProcessChain(xmlTextReaderPtr reader) } if (sName=="backprojector") { logger(kipl::logging::Logger::LogVerbose,"Parsing backproj"); - backprojector.setAppPath(m_sApplicationPath); + backprojector.setAppPath(m_sApplicationPath,"BackProjectors"); backprojector.ParseModule(reader); } diff --git a/frameworks/tomography/UnitTests/tFDKBackProjectors/CMakeLists.txt b/frameworks/tomography/UnitTests/tFDKBackProjectors/CMakeLists.txt index 706b8f84b..e4c15ff11 100644 --- a/frameworks/tomography/UnitTests/tFDKBackProjectors/CMakeLists.txt +++ b/frameworks/tomography/UnitTests/tFDKBackProjectors/CMakeLists.txt @@ -24,21 +24,6 @@ include_directories( ../../../../core/kipl/kipl/include/ ../../../../core/algorithms/ImagingAlgorithms/include ) -# if (APPLE) -# include_directories( -# ../../../../../ExternalDependencies/macos/include -# ) -# endif() - -# if (WIN32) -# include_directories( -# ../../../../../ExternalDependencies/windows/include -# ../../../../../ExternalDependencies/windows/include/nexus -# ../../../../../ExternalDependencies/windows/include/cfitsio -# ../../../../../ExternalDependencies/windows/include/libxml2 -# ../../../../external/include/ -# ) -# endif() set(SRC_FILES tst_FDKBackprojectors.cpp)