Bent
Bent

Reputation: 1385

CMake unable to link libxml2 in CLion

tl;dr add set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" ) to CMakeLists.txt (more infos below).


I want to run a very simple application within CLion. This application uses libxml2.

I use CLion 2018.1.2 on Ubuntu 18.04 LTS, libxml2-dev is properly installed.

My project does compile with:

g++ -I /usr/include/libxml2 xmlTest.cpp -o xmlTest.exe -lxml2

it does not compile in CLion though, using this CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(xmlTest)

set(CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2 -lxml2 -lz -lm")

include_directories( /usr/local/include/libxml2 )

add_executable (xmlTest.exe xmlTest.cpp)

the compiler throws me:

/home/xxxx/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/181.4668.70/bin/cmake/bin/cmake --build /home/xxxx/src/cmake-build-debug --target xmlTest.exe -- -I /usr/include/libxml2 -lxml2
Scanning dependencies of target xmlTest.exe
[ 50%] Building CXX object CMakeFiles/xmlTest.exe.dir/xmlTest.cpp.o
[100%] Linking CXX executable xmlTest.exe
CMakeFiles/xmlTest.exe.dir/xmlTest.cpp.o: In function `main':
/home/xxxx/src/xmlTest.cpp:10: undefined reference to `xmlReadFile'
/home/xxxx/src/xmlTest.cpp:17: undefined reference to `xmlDocGetRootElement'
/home/xxxx/src/xmlTest.cpp:21: undefined reference to `xmlFreeDoc'
/home/xxxx/src/xmlTest.cpp:25: undefined reference to `xmlStrcmp'
/home/xxxx/src/xmlTest.cpp:27: undefined reference to `xmlFreeDoc'

my application (xmlTest.cpp):

#include <stdlib.h>
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

int main(int argc, char const *argv[]) {
  xmlDocPtr doc;
  xmlNodePtr cur;

  doc = xmlReadFile(argv[1], NULL, 0);

  if (doc == NULL ) {
    fprintf(stderr,"Document not parsed successfully. \n");
    return 1;
  }

  cur = xmlDocGetRootElement(doc);

  if (cur == NULL) {
    fprintf(stderr,"empty document\n");
    xmlFreeDoc(doc);
    return 1;
  }

  if (xmlStrcmp(cur->name, (const xmlChar *) "users")) {
    fprintf(stderr,"document of the wrong type, root node != story");
    xmlFreeDoc(doc);
    return 1;
  }

  return 0;
}

after fiddling with libxml2 and CMake for hours now without success, I am open to any idea what to do to tell CMake libxml2 actually exists...


Update #1:

thanks to @vre's suggestion I updated my CMakeLists.txt file:

cmake_minimum_required(VERSION 3.10)
project(xmlTest)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2 -lxml2 -lz -lm")
set(CMAKE_CXX "/usr/local/include/libxml2")
find_library(libxml2 libxml2)
link_directories(/usr/local/include/libxml2)
add_compile_options("-I/usr/include/libxml2 -lxml2 -lz -lm")
find_package(LibXml2 REQUIRED)
add_executable (xmlTest.exe xmlTest.cpp)
target_compile_definitions(xmlTest.exe PUBLIC ${LibXml2_DEFINITIONS})
target_include_directories(xmlTest.exe PUBLIC ${LibXml2_INCLUDE_DIRS})
target_link_libraries(xmlTest.exe ${LibXml2_LIBRARIES})

This did not change or resolve the error though.

Update #2 (solution):

this is how to build projects with libxml2 in CLion:

cmake_minimum_required(VERSION 3.10)
project(xmlTest)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -I/usr/include/libxml2")
set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" )

add_executable (xmlTest.exe xmlTest.cpp)

My issue was that I had the wrong order of arguments in my CMAKE_CXX_FLAGS. This article points this out. Using set(CMAKE_CXX_STANDARD_LIBRARIES "-lxml2" ) was the key (see this)

I hope this helps some future timetravelers:

Upvotes: 2

Views: 1568

Answers (1)

vre
vre

Reputation: 6744

The solution you came up with works but the intention of CMake is to provide means to express a platform, compiler, and build tool independent way of describing projects. All the magic happens in the FindLibXml2.cmake module. And a huge number of modules are delivered ready to use with your CMake installation. See the modules directory under /usr/share/cmake-3.10/Modules on Ubuntu 18.04.

If you reformulate your CMakeLists.txt the following way:

cmake_minimum_required(VERSION 3.10)

project(xmlTest)

set(CMAKE_CXX_STANDARD 11)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
elseif(MSVC)
  # add options for Visual C/C++ Compiler here
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()    

find_package(LibXml2 REQUIRED)

add_executable(xmlTest.exe xmlTest.cpp)

target_compile_definitions(xmlTest.exe PUBLIC ${LIBXML2_DEFINITIONS})
target_include_directories(xmlTest.exe PUBLIC ${LIBXML2_INCLUDE_DIRS})
target_link_libraries(xmlTest.exe ${LIBXML2_LIBRARIES})

you are able to work on a wide range of platforms and combinations of compilers and IDEs. This was tested on Ubuntu 18.04 with GCC 7.3 and Windows 10 with MSVC 15. You need some more steps to build on Windows (i.e. installing and setup libxml2 and all of its dependencies). And this should work with CLion too out of the box.

Upvotes: 3

Related Questions