View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0015852 | Scribus | Build System | public | 2019-10-14 02:29 | 2020-08-11 20:56 |
Reporter | bkylerussell | Assigned To | cbradney | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | reopened | ||
Product Version | 1.5.6.svn | ||||
Fixed in Version | 1.5.6.svn | ||||
Summary | 0015852: [PATCH] CMake can't locate some icu-uc headers with pkg-config | ||||
Description | A couple of libraries that depend on icu-uc headers don't use the pkg_check_modules provided ${ICU_INCLUDEDIR} variable to correctly configure their include_directories. I encountered this configuration error when icu4c was installed using brew. $ brew install harfbuzz ... ==> Installing harfbuzz dependency: icu4c ... For pkg-config to find icu4c you may need to set: export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig" $ cmake ../Scribus ... -- Package 'icu-uc', required by 'harfbuzz-icu', not found CMake Error at /usr/local/Cellar/cmake/3.15.4/share/cmake/Modules/FindPkgConfig.cmake:458 (message): A required package was not found Call Stack (most recent call first): /usr/local/Cellar/cmake/3.15.4/share/cmake/Modules/FindPkgConfig.cmake:637 (_pkg_check_modules_internal) CMakeLists_Dependencies.cmake:319 (pkg_check_modules) CMakeLists.txt:358 (include) -- Configuring incomplete, errors occurred! $ export PKG_CONFIG_PATH=/usr/local/opt/icu4c/lib/pkgconfig/ $ make ... In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/styles/linestyle.cpp:18: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/prefsmanager.h:28: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/prefsstructs.h:24: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/pdfoptions.h:21: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/scribusstructs.h:32: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/pageitem.h:50: /Users/bkylerussell/code/scribus/Scribus/scribus/text/storytext.h:33:10: fatal error: 'unicode/brkiter.h' file not found #include <unicode/brkiter.h> ^~~~~~~~~~~~~~~~~~~ 1 error generated. ... [ 7%] Building CXX object scribus/third_party/rtf-qt/CMakeFiles/scribus_rtf_lib.dir/sladocumentrtfoutput.cpp.o In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/third_party/rtf-qt/sladocumentrtfoutput.cpp:20: In file included from /Users/bkylerussell/code/scribus/Scribus/scribus/pageitem.h:50: /Users/bkylerussell/code/scribus/Scribus/scribus/text/storytext.h:33:10: fatal error: 'unicode/brkiter.h' file not found #include <unicode/brkiter.h> ^~~~~~~~~~~~~~~~~~~ 1 error generated. | ||||
Tags | patch | ||||
Patch | Yes | ||||
|
Patch file for missing icu header includes icu-headers.diff (868 bytes)
Index: Scribus/scribus/styles/CMakeLists.txt =================================================================== --- Scribus/scribus/styles/CMakeLists.txt (revision 23255) +++ Scribus/scribus/styles/CMakeLists.txt (working copy) @@ -2,6 +2,7 @@ ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/scribus ${FREETYPE_INCLUDE_DIRS} + ${ICU_INCLUDE_DIRS} ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_FPIC}") Index: Scribus/scribus/third_party/rtf-qt/CMakeLists.txt =================================================================== --- Scribus/scribus/third_party/rtf-qt/CMakeLists.txt (revision 23255) +++ Scribus/scribus/third_party/rtf-qt/CMakeLists.txt (working copy) @@ -2,6 +2,7 @@ ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/scribus ${FREETYPE_INCLUDE_DIRS} +${ICU_INCLUDE_DIRS} ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_FPIC}") |
|
Already fixed in r21563 |
|
Are you sure r21563 resolves this? It looks like r21563 sets up the main CMakeLists.txt with the proper icu pkgconfig, but the error I encountered was building some of the subdirectories (scribus/third_party/rtf-qt and scribus/styles). I just wanted to make sure I understand. I'm not very familiar with the scribus build files, but would like to get more involved. |
|
I checked unicode/brkiter.h was supplied by ICU.. and that is not used in scribus/styles, for example. I'm not sure why we would need the ICU includes for that subdirectory? |
|
It's not directly included in scribus/styles, but there's an include dependency chain about six header files deep from styles/linestyle.cpp that causes unicode/brkiter.h to be included (ultimately via text/storytext.h). If there's somewhere to break that dependency chain from styles, then I agree that would be a better fix, but I'll defer to you. Otherwise, it does look like styles needs to be able to find unicode/brkiter.h in order for the compiler to resolve all its includes. Similarly from third_party/rtf-qt/sladocumentrtfoutput.cpp, although the chain is much shorter. scribus/pageitem.h appears to be the common include between styles and third_party/rtf-qt. |
|
What OS are you building on? |
|
macOS 10.15 right now. I may have been running 10.14 at the time, but I'm not exactly sure. I don't think I was using any non-default configure options. |
|
same.. 10.14 and 10.15 on multiple machines |
|
Did you use brew to install the icu dependency? Maybe <unicode/brkiter.h> on your system is in the default include search path? What do your compile lines for styles/linestyle.cpp and third_party/rtf-qt/sladocumentrtfoutput.cpp look like? I think either those two cpp files must not be compiling in your setup like they did in mine (which I'm guessing is unlikely?), or your system has the <unicode/brkiter.h> header installed in a default include search path. The only version I found on my system was /usr/local/Cellar/icu4c/64.2/include/unicode/brkiter.h, so I can't imagine that the compiler would look there without the includedir directive from the icu-uc pkg-config file. I'm not sure why my system is configured differently (brew?). I thought I had seen somewhere in the wiki that brew was supposed to be a supported setup for Scribus dev environment, but maybe not? It would be helpful for it to work. I also see ${ICU_INCLUDE_DIRS} used in Scribus/scribus/text/CMakeLists.txt, which was added in r21563 like you said. It looks like pageitem.h gets included from text/ as well, so that all checks out. I think these other two cases just got missed somehow. |
|
I use MacPorts. Here's my line for linestyle.cpp: [ 0%] Building CXX object scribus/styles/CMakeFiles/scribus_styles_lib.dir/linestyle.cpp.o cd /Users/craig/scribus/PostTrunk/bt514/scribus/styles && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -DAPPDATADIR=\"/Users/craig/Applications/Scribus.app/Contents/share/metainfo/\" -DDESKTOPDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/applications/\" -DDOCDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/doc/scribus/\" -DHAVE_CONFIG_H -DHAVE_DLFCN_H -DHAVE_SVNVERSION -DHAVE_UNISTD_H -DICONDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/icons/\" -DLIBDIR=\"/Users/craig/Applications/Scribus.app/Contents/lib/\" -DPLUGINDIR=\"/Users/craig/Applications/Scribus.app/Contents/lib/\" -DQMLDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/qml/\" -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_OPENGL_LIB -DQT_PRINTSUPPORT_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -DSAMPLESDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/samples/\" -DSCRIPTSDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/scripts/\" -DSHAREDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/\" -DTEMPLATEDIR=\"/Users/craig/Applications/Scribus.app/Contents/share/scribus/templates/\" -I/Users/craig/scribus/PostTrunk/bt514/scribus/styles -I/Users/craig/scribus/PostTrunk/trunk/Scribus/scribus/styles -F/Users/craig/Qt/5.14.2/clang_64/lib -I/Users/craig/Qt/5.14.2/clang_64/lib/QtCore.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/./mkspecs/macx-clang -I/Users/craig/Qt/5.14.2/clang_64/lib/QtWidgets.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/lib/QtGui.framework/Headers -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/OpenGL.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/lib/QtXml.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/lib/QtNetwork.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/lib/QtOpenGL.framework/Headers -I/Users/craig/Qt/5.14.2/clang_64/lib/QtPrintSupport.framework/Headers -I/Users/craig/scribus/PostTrunk/bt514 -I/Users/craig/scribus/PostTrunk/bt514/scribus -I/opt/local/include -I/opt/local/include/libxml2 -I/Users/craig/scribus/PostTrunk/trunk/Scribus -I/Users/craig/scribus/PostTrunk/trunk/Scribus/scribus -I/opt/local/include/freetype2 -g -O0 -g -fno-inline-functions -Wall -mmacosx-version-min=10.14 -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -mmacosx-version-min=10.14 -fPIC -DCOMPILE_SCRIBUS_MAIN_APP -std=gnu++11 -o CMakeFiles/scribus_styles_lib.dir/linestyle.cpp.o -c /Users/craig/scribus/PostTrunk/trunk/Scribus/scribus/styles/linestyle.cpp I don't see the dependency on that file for those two files though. |
|
I didn't notice too many significant differences in our compile lines for linestyle.cpp, but I'm guessing macports installed /opt/local/include/unicode/brkiter.h on your system. My patch adds -I/usr/local/Cellar/icu4c/64.2/include to my compile line, which is where brew installed the header for me. I looked more closely at linestyle.cpp, and it doesn't actually need to include prefsmanager.h, so just removing that include fixes that file, but I hit the same include dependency chain on styles/charstyle.cpp, which does grab a PrefsManager instance in ScFace parse<ScFace>(const Xml_string& str). Is there another way to get to the right AvailFonts instance without going through PrefsManager? prefsmanager.h is one header that causes <unicode/brkiter.h> to be needed. third_party/rtf-qt/sladocumentrtfoutput.cpp appears to be more complicated, even if the above charstyle.cpp PrefsManager case can be resolved. |
|
I installed macports and verified that the icu port does in fact provide /opt/local/include/unicode/brkiter.h, and since -I/opt/local/include is provided on your compile line (probably through some other CMake include_directory), that's why it compiles successfully on your system. $ port contents icu | grep brkiter.h /opt/local/include/unicode/brkiter.h I'll assume ${LCMS2_INCLUDE_DIR} provides -I/opt/local/include from your root CMakeLists.txt since ${LCMS2_INCLUDE_DIR} is listed right before ${LIBXML2_INCLUDE_DIR}, which corresponds with the position of -I/opt/local/include on your compile command line. It looks like the lcms2 pc file only specifies -I${includedir}, so if macports builds its packages with /opt/local/include as the default ${includedir}, that does seem like the culprit. To check that, you could try removing ${LCMS2_INCLUDE_DIR} in the root CMakeLists.txt and you'll probably hit the same error I received building styles/, assuming /opt/local/include isn't being added back to the compile line from anywhere else. Lots of other things may break too though since macports seems to put lots of things in /opt/local/include. #Set up include dirs with all found packages include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/scribus ${QT_INCLUDES} ${FREETYPE_INCLUDE_DIR} # ${FONTCONFIG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${LCMS2_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${TIFF_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${OSG_INCLUDE_DIR} ${GSL_INCLUDE_DIR} ) In summary, I think there is a deficiency in at least one CMakeLists.txt file. It only works currently because someone else (not the actual icu pkg-config) is putting /opt/local/include on the compile line for you. If that stops happening (for example, by removing ${LCMS2_INCLUDE_DIR}), or icu gets installed somewhere else (like on my system), then you're going to hit this error. I understand styles/linestyle.cpp doesn't include <unicode/brkiter.h> directly, but it is a transitive dependency. So that transitive dependency should either be broken, or the correct ${ICU_INCLUDE_DIR} provided somewhere. Since this transitive dependency seems to involve several global headers (like scribusstructs.h), maybe you're suggesting ${ICU_INCLUDE_DIR} would be better placed in the root CMakeLists.txt include_directories (listed above)? My patch only added ${ICU_INCLUDE_DIR} in the styles/ and third_party/rtf-qt/ because I generally try to avoid global, implicit dependencies, as they can be hard to unwind. But I would be glad to try adding it to the root CMakeLists.txt and provide an updated patch if you like that solution better. Also, I understand brew's behavior a little better now too. It typically links things in /usr/local to its custom install path, but it warns it does not do that for icu to avoid conflicting with the macOS provided libicucore.dylib. (My compile line does have -I/usr/local/include.) But for that conflict, this would all behave the same. But the CMakeLists.txt files here are not technically allowing the install/configuration flexibility that pkg-config was designed to support. |
|
Ok, I dug in further. :) scribus/text/storytext.h is the actual header file pulling in <unicode/brkiter.h> for everyone (including clients that actually use it). I can remove <unicode/brkiter.h> from the header file by forward-declaring icu::BreakIteartor, but properly forward declaring that class requires <unicode/uversion.h> since icu is an aliased namespace against a version-specific icu namespace (see "Namespaces" under http://userguide.icu-project.org/dev/codingguidelines#TOC-C-Coding-Guidelines), which puts us back into the position of requiring an icu header in scribus/text/storytext.h. So I tried including ${ICU_INCLUDE_DIRS} in scribus/CMakeLists.txt since pageitem.h is a top-level header file, and that seems to work, if you like that approach better than in the original two CMakeLists.txt files I chose. (See the icu-headers-v2.diff attachment.) I also attached a patch to remove an unused prefsmanger.h header from linestyle.cpp because it kept getting in my way (see linestyle-unused-prefsmanager.diff). Thirdly, I attached a patch from the path I started down trying to remove <unicode/brkiter.h> from storytext.h (see remove-using-icu-from-storytext.diff). There's shouldn't be any significant different, but it does remove the 'using namespace icu;' line from storytext.h in favor of forward-declaration. I try to avoid 'using namespace' in header files when possible, so I thought there might be some interest in this. It still requires a unicode header though, so depends on the icu-headers-v2.diff patch. It's possible there's a way to avoid even <unicode/uversion.h> by turning off the icu namespace versioning flag, but that involves other complications, and I didn't want to track down all the ways Scribus uses icu. icu-headers-v2.diff (929 bytes)
Index: scribus/CMakeLists.txt =================================================================== --- scribus/CMakeLists.txt (revision 23587) +++ scribus/CMakeLists.txt (working copy) @@ -21,6 +21,15 @@ add_definitions(-DQT_DLL) endif() +include_directories( + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${FREETYPE_INCLUDE_DIRS} + ${HARFBUZZ_INCLUDE_DIRS} + ${ICU_INCLUDE_DIRS} +) + add_subdirectory(dtd) add_subdirectory(colormgmt) add_subdirectory(desaxe) @@ -1151,14 +1160,6 @@ set(SCRIBUS_ZIP_LIB "scribus_zip_lib") set(SCRIBUS_RTF_LIB "scribus_rtf_lib") -include_directories( - ${CMAKE_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${FREETYPE_INCLUDE_DIRS} - ${HARFBUZZ_INCLUDE_DIRS} -) - if (GMAGICK_FOUND) message(STATUS "GMAGICK: Libs: ${GMAGICK_LDFLAGS}, Inc: ${GMAGICK_INCLUDE_DIRS}, Ldflags: ${GMAGICK_LDFLAGS}") include_directories( linestyle-unused-prefsmanager.diff (368 bytes)
Index: scribus/styles/linestyle.cpp =================================================================== --- scribus/styles/linestyle.cpp (revision 23587) +++ scribus/styles/linestyle.cpp (working copy) @@ -15,7 +15,6 @@ #include "linestyle.h" #include "desaxe/saxiohelper.h" #include "desaxe/simple_actions.h" -#include "prefsmanager.h" #include "util_math.h" remove-using-icu-from-storytext.diff (3,833 bytes)
Index: scribus/text/boxes.cpp =================================================================== --- scribus/text/boxes.cpp (revision 23587) +++ scribus/text/boxes.cpp (working copy) @@ -6,6 +6,7 @@ */ #include <cmath> +#include <unicode/brkiter.h> #include "pageitem.h" #include "boxes.h" @@ -21,6 +22,8 @@ #include "itextcontext.h" #include "itextsource.h" +using namespace icu; + int GroupBox::pointToPosition(QPointF coord, const StoryText &story) const { QPointF rel = coord - QPointF(m_x, m_y); Index: scribus/hyphenator.cpp =================================================================== --- scribus/hyphenator.cpp (revision 23587) +++ scribus/hyphenator.cpp (working copy) @@ -29,6 +29,7 @@ #include <QCursor> #include <QCheckBox> #include <QByteArray> +#include <unicode/brkiter.h> #include "langmgr.h" #include "scpaths.h" @@ -37,6 +38,8 @@ #include "prefsfile.h" #include "prefsmanager.h" +using namespace icu; + Hyphenator::Hyphenator(QWidget* parent, ScribusDoc *dok) : QObject( parent ), m_doc(dok), m_hdict(nullptr), Index: scribus/text/storytext.cpp =================================================================== --- scribus/text/storytext.cpp (revision 23587) +++ scribus/text/storytext.cpp (working copy) @@ -22,6 +22,8 @@ ***************************************************************************/ //#include <QDebug> +#include <unicode/brkiter.h> + //FIXME: this include must go to sctextstruct.h ! #include <QList> #include <cassert> //added to make Fedora-5 happy @@ -40,6 +42,7 @@ #include "desaxe/simple_actions.h" #include "shapedtextcache.h" +using namespace icu; StoryText::StoryText(ScribusDoc * doc_) : m_doc(doc_) { Index: scribus/text/storytext.h =================================================================== --- scribus/text/storytext.h (revision 23587) +++ scribus/text/storytext.h (working copy) @@ -29,9 +29,8 @@ #include <QObject> #include <QString> #include <QList> +#include <unicode/uversion.h> -#include <unicode/brkiter.h> - #include "itextsource.h" #include "marks.h" #include "text/frect.h" @@ -50,7 +49,9 @@ class ResourceCollection; class ShapedTextCache; -using namespace icu; +U_NAMESPACE_BEGIN +class BreakIterator; +U_NAMESPACE_END /** * This class holds the text of a Scribus textframe and pointers to its @@ -258,10 +259,10 @@ bool isSelected() const; // break iterators - static BreakIterator* getGraphemeIterator(); - static BreakIterator* getWordIterator(); - static BreakIterator* getSentenceIterator(); - static BreakIterator* getLineIterator(); + static icu::BreakIterator* getGraphemeIterator(); + static icu::BreakIterator* getWordIterator(); + static icu::BreakIterator* getSentenceIterator(); + static icu::BreakIterator* getLineIterator(); // layout helpers @@ -295,10 +296,10 @@ ScribusDoc * m_doc; int m_selFirst, m_selLast; ShapedTextCache* m_shapedTextCache; - static BreakIterator* m_graphemeIterator; - static BreakIterator* m_wordIterator; - static BreakIterator* m_sentenceIterator; - static BreakIterator* m_lineIterator; + static icu::BreakIterator* m_graphemeIterator; + static icu::BreakIterator* m_wordIterator; + static icu::BreakIterator* m_sentenceIterator; + static icu::BreakIterator* m_lineIterator; QString textWithSoftHyphens (int pos, uint len) const; void insertCharsWithSoftHyphens(int pos, const QString& txt, bool applyNeighbourStyle = false); Index: scribus/text/textshaper.cpp =================================================================== --- scribus/text/textshaper.cpp (revision 23587) +++ scribus/text/textshaper.cpp (working copy) @@ -3,6 +3,7 @@ #include <harfbuzz/hb.h> #include <harfbuzz/hb-ft.h> #include <harfbuzz/hb-icu.h> +#include <unicode/brkiter.h> #include <unicode/ubidi.h> #include "scrptrun.h" |
|
Thanks, I have applied those three patches in r23660. |
Date Modified | Username | Field | Change |
---|---|---|---|
2019-10-14 02:29 | bkylerussell | New Issue | |
2019-10-14 02:33 | bkylerussell | File Added: icu-headers.diff | |
2019-10-14 02:33 | bkylerussell | Note Added: 0046775 | |
2019-10-14 07:06 | ale | Summary | CMake can't locate some icu-uc headers with pkg-config => [PATCH] CMake can't locate some icu-uc headers with pkg-config |
2019-10-14 07:06 | ale | Tag Attached: patch | |
2020-04-10 21:35 | cbradney | Assigned To | => cbradney |
2020-04-10 21:35 | cbradney | Status | new => resolved |
2020-04-10 21:35 | cbradney | Resolution | open => fixed |
2020-04-10 21:35 | cbradney | Note Added: 0047504 | |
2020-04-10 23:00 | bkylerussell | Status | resolved => feedback |
2020-04-10 23:00 | bkylerussell | Resolution | fixed => reopened |
2020-04-10 23:00 | bkylerussell | Note Added: 0047506 | |
2020-04-10 23:06 | cbradney | Note Added: 0047507 | |
2020-04-11 01:34 | bkylerussell | Note Added: 0047508 | |
2020-04-11 01:34 | bkylerussell | Status | feedback => assigned |
2020-04-12 19:54 | cbradney | Note Added: 0047512 | |
2020-04-13 13:40 | bkylerussell | Note Added: 0047513 | |
2020-04-14 09:21 | cbradney | Note Added: 0047517 | |
2020-04-17 04:08 | bkylerussell | Note Added: 0047536 | |
2020-04-19 12:46 | cbradney | Note Added: 0047540 | |
2020-04-21 03:18 | bkylerussell | Note Added: 0047546 | |
2020-04-22 14:03 | bkylerussell | Note Added: 0047551 | |
2020-04-25 18:21 | bkylerussell | File Added: icu-headers-v2.diff | |
2020-04-25 18:21 | bkylerussell | File Added: linestyle-unused-prefsmanager.diff | |
2020-04-25 18:21 | bkylerussell | File Added: remove-using-icu-from-storytext.diff | |
2020-04-25 18:21 | bkylerussell | Note Added: 0047568 | |
2020-04-26 20:15 | cbradney | Note Added: 0047570 | |
2020-04-26 20:15 | cbradney | Status | assigned => resolved |
2020-04-26 20:16 | cbradney | Product Version | => 1.5.6.svn |
2020-04-26 20:16 | cbradney | Fixed in Version | => 1.5.6.svn |
2020-08-11 20:56 | cbradney | Status | resolved => closed |