set up Xerces on ubuntu 12.04 to use with cmake and clang

3k views Asked by At

I want to use Xerces in my project, which I compile with the help of cmake and clang.

What I did is:

  • download source
  • extract it to a folder called 'xerces-c-3.1.1'
  • cd into that folder
  • ./configure
  • make
  • make install

Then I wrote LINK_DIRECTORIES(/usr/local/lib) into my CMakeLists.txt, and #include <xercesc/parsers/XercesDOMParser.hpp> into my main.cpp.

It compiles fine, but linking doesn't work. I get the following results:

Linking CXX executable DG5_RE
CMakeFiles/DG5_RE.dir/main.cpp.o: In function `xercesc_3_1::XMLAttDefList::~XMLAttDefList()':
/home/reissmann/Dokumente/DGFromRepo/Source_Cpp_RE/main.cpp:(.text._ZN11xercesc_3_113XMLAttDefListD0Ev[_ZN11xercesc_3_113XMLAttDefListD0Ev]+0x1e): undefined reference to `xercesc_3_1::XMemory::operator delete(void*)'
CMakeFiles/DG5_RE.dir/main.cpp.o: In function `xercesc_3_1::DTDEntityDecl::~DTDEntityDecl()':
/home/reissmann/Dokumente/DGFromRepo/Source_Cpp_RE/main.cpp:(.text._ZN11xercesc_3_113DTDEntityDeclD0Ev[_ZN11xercesc_3_113DTDEntityDeclD0Ev]+0x1e): undefined reference to `xercesc_3_1::XMemory::operator delete(void*)'
CMakeFiles/DG5_RE.dir/main.cpp.o: In function `xercesc_3_1::DTDEntityDecl::~DTDEntityDecl()':
/home/reissmann/Dokumente/DGFromRepo/Source_Cpp_RE/main.cpp:(.text._ZN11xercesc_3_113DTDEntityDeclD2Ev[_ZN11xercesc_3_113DTDEntityDeclD2Ev]+0x11): undefined reference to `xercesc_3_1::XMLEntityDecl::~XMLEntityDecl()'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113XMLAttDefListE[_ZTVN11xercesc_3_113XMLAttDefListE]+0x20): undefined reference to `xercesc_3_1::XMLAttDefList::isSerializable() const'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113XMLAttDefListE[_ZTVN11xercesc_3_113XMLAttDefListE]+0x28): undefined reference to `xercesc_3_1::XMLAttDefList::serialize(xercesc_3_1::XSerializeEngine&)'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113XMLAttDefListE[_ZTVN11xercesc_3_113XMLAttDefListE]+0x30): undefined reference to `xercesc_3_1::XMLAttDefList::getProtoType() const'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113DTDEntityDeclE[_ZTVN11xercesc_3_113DTDEntityDeclE]+0x20): undefined reference to `xercesc_3_1::DTDEntityDecl::isSerializable() const'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113DTDEntityDeclE[_ZTVN11xercesc_3_113DTDEntityDeclE]+0x28): undefined reference to `xercesc_3_1::DTDEntityDecl::serialize(xercesc_3_1::XSerializeEngine&)'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTVN11xercesc_3_113DTDEntityDeclE[_ZTVN11xercesc_3_113DTDEntityDeclE]+0x30): undefined reference to `xercesc_3_1::DTDEntityDecl::getProtoType() const'
CMakeFiles/DG5_RE.dir/main.cpp.o:(.rodata._ZTIN11xercesc_3_113DTDEntityDeclE[_ZTIN11xercesc_3_113DTDEntityDeclE]+0x10): undefined reference to `typeinfo for xercesc_3_1::XMLEntityDecl'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [DG5_RE] Fehler 1
make[1]: *** [CMakeFiles/DG5_RE.dir/all] Fehler 2
make: *** [all] Fehler 2

What went wrong, and what is the appropriate solution? Many thanks in advance.

2

There are 2 answers

3
Fraser On BEST ANSWER

You probably want to replace your use of link_directories with find_library and target_link_libraries.

link_directories only provides paths which the linker can search for dependencies - it doesn't actually specify what those dependencies are. Furthermore, from the docs:

Note that this command is rarely necessary. Library locations returned by find_package() and find_library() are absolute paths. Pass these absolute library file paths directly to the target_link_libraries() command. CMake will ensure the linker finds them.

I'm not familiar with Xerces, but assuming it has only 1 library called "libxerces-c.a", you should probably have something like:

find_library(XercesLibrary NAMES xerces-c PATHS /usr/local/lib)
if(NOT XercesLibrary)
  message(FATAL_ERROR "Failed to find the Xerces library.")
endif()
...
target_link_libraries(MyExe ${XercesLibrary})

You may need to significantly extend this find_library process; more PATHS than just /usr/local/lib could be given; you may need to find more than 1 library (e.g. a Debug version on Windows?), etc. If the library has different names on different operating systems, you may need to provide more NAME options (remember CMake may adjust the search name - see CMAKE_FIND_LIBRARY_PREFIXES and CMAKE_FIND_LIBRARY_SUFFIXES).

Also, a more helpful error message can be invaluable if the find attempt fails. You could suggest to set a variable (e.g. XERCES_LIB_DIR) indicating the location of the Xerces library, and this could be added to the list of PATHS in the find_library call.

0
Yuchen On

Use the FindXercesC is an easy and quick solution.

include(FindXercesC)
find_package(XercesC REQUIRED)
include_directories( ${XercesC_INCLUDE_DIR} )

target_link_libraries ( ${PROJECT_NAME} ${XercesC_LIBRARY} )