trying to work out how to use XercesC as Fetched Content

We are trying the out various ways of including external libraries we have in a cpp project and have hit a problem using fetchcontent to download/configure xerces-c. Everything seems to download and build ok, but we can’t link to its lib or include any of its headers.
The properties XercesC_INCLUDE_DIR and XercesC_LIBRARY don’t appear to have been set anywhere.

I’ve included the cmakelists.txt below, we are quite new to this technology and expect something to be wrong with it, just wondering if anyone has tried to do this before, or may have suggestions to fix it.

Many thanks.

cmake_minimum_required(VERSION 3.15)
project(ParseXMLFC)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)
include(FetchContent)

FetchContent_Declare(
  fmt
  GIT_REPOSITORY https://github.com/fmtlib/fmt.git
  GIT_TAG master
  OVERRIDE_FIND_PACKAGE
)
set(XERCES_VERSION 3.2.5)
FetchContent_Declare(
	XERCES
	URL https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCES_VERSION}.tar.gz
	OVERRIDE_FIND_PACKAGE
	DOWNLOAD_EXTRACT_TIMESTAMP On
)
find_package(fmt)
find_package(XERCES)

set(INCLUDE_DIRS ${XercesC_INCLUDE_DIR}) # <------------------ not set
set(SOURCE_FILES
	main.cpp
)
include_directories(${SRC_DIRS} ${INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(
	${PROJECT_NAME}
	PRIVATE
	XercesC::XercesC  # <------------------ not set
	fmt::fmt-header-only
)
message(STATUS "!!! CMAKE_FIND_PACKAGE_REDIRECTS_DIR: ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/${${xerces-c}}")
message(STATUS "!!! XercesC_INCLUDE_DIR: ${XercesC_INCLUDE_DIR}")  # <------------------ not set
message(STATUS "!!! XercesC_LIBRARY: ${XercesC_LIBRARY}")  # <------------------ not set
message(STATUS "!!! XercesC_LIBRARIES: ${XercesC_LIBRARIES}")  # <------------------ not set

When run with cmake -B build, this is output:

NOTICE the empty XercesC_INCLUDE_DIR and XercesC_LIBRARY

-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.26100.
-- The C compiler identification is MSVC 19.42.34226.3
-- The CXX compiler identification is MSVC 19.42.34226.3
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.42.34226/bin/Hostarm64/arm64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.42.34226/bin/Hostarm64/arm64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- {fmt} version: 11.0.2
-- Build type:
-- Configuring Apache Xerces-C++ version 3.2.5
-- Performing Test CXX_FLAG_W3
-- Performing Test CXX_FLAG_W3 - Success
-- Looking for C++ include arpa/inet.h
-- Looking for C++ include arpa/inet.h - not found
-- Looking for C++ include dlfcn.h
-- Looking for C++ include dlfcn.h - not found
-- Looking for C++ include fcntl.h
-- Looking for C++ include fcntl.h - found
-- Looking for C++ include float.h
-- Looking for C++ include float.h - found
-- Looking for C++ include langinfo.h
-- Looking for C++ include langinfo.h - not found
-- Looking for C++ include limits.h
-- Looking for C++ include limits.h - found
-- Looking for C++ include locale.h
-- Looking for C++ include locale.h - found
-- Looking for C++ include memory.h
-- Looking for C++ include memory.h - found
-- Looking for C++ include netdb.h
-- Looking for C++ include netdb.h - not found
-- Looking for C++ include netinet/in.h
-- Looking for C++ include netinet/in.h - not found
-- Looking for C++ include nl_types.h
-- Looking for C++ include nl_types.h - not found
-- Looking for C++ include stdbool.h
-- Looking for C++ include stdbool.h - found
-- Looking for C++ include stddef.h
-- Looking for C++ include stddef.h - found
-- Looking for C++ include stdlib.h
-- Looking for C++ include stdlib.h - found
-- Looking for C++ include string.h
-- Looking for C++ include string.h - found
-- Looking for C++ include strings.h
-- Looking for C++ include strings.h - not found
-- Looking for C++ include sys/param.h
-- Looking for C++ include sys/param.h - not found
-- Looking for C++ include sys/socket.h
-- Looking for C++ include sys/socket.h - not found
-- Looking for C++ include sys/stat.h
-- Looking for C++ include sys/stat.h - found
-- Looking for C++ include sys/time.h
-- Looking for C++ include sys/time.h - not found
-- Looking for C++ include sys/timeb.h
-- Looking for C++ include sys/timeb.h - found
-- Looking for C++ include sys/types.h
-- Looking for C++ include sys/types.h - found
-- Looking for C++ include unistd.h
-- Looking for C++ include unistd.h - not found
-- Looking for C++ include wchar.h
-- Looking for C++ include wchar.h - found
-- Looking for C++ include wctype.h
-- Looking for C++ include wctype.h - found
-- Looking for C++ include endian.h
-- Looking for C++ include endian.h - not found
-- Looking for C++ include machine/endian.h
-- Looking for C++ include machine/endian.h - not found
-- Looking for C++ include arpa/nameser_compat.h
-- Looking for C++ include arpa/nameser_compat.h - not found
-- Looking for getcwd
-- Looking for getcwd - found
-- Looking for pathconf
-- Looking for pathconf - not found
-- Looking for realpath
-- Looking for realpath - not found
-- Looking for getaddrinfo
-- Looking for getaddrinfo - not found
-- Looking for gethostbyaddr
-- Looking for gethostbyaddr - not found
-- Looking for gethostbyname
-- Looking for gethostbyname - not found
-- Looking for socket
-- Looking for socket - not found
-- Looking for clock_gettime
-- Looking for clock_gettime - not found
-- Looking for ftime
-- Looking for ftime - found
-- Looking for gettimeofday
-- Looking for gettimeofday - not found
-- Looking for gmtime_r
-- Looking for gmtime_r - not found
-- Looking for memmove
-- Looking for memmove - found
-- Looking for memset
-- Looking for memset - found
-- Looking for nl_langinfo
-- Looking for nl_langinfo - not found
-- Looking for setlocale
-- Looking for setlocale - found
-- Looking for localeconv
-- Looking for localeconv - found
-- Looking for snprintf
-- Looking for snprintf - not found
-- Looking for strcasecmp
-- Looking for strcasecmp - not found
-- Looking for strncasecmp
-- Looking for strncasecmp - not found
-- Looking for stricmp
-- Looking for stricmp - found
-- Looking for strnicmp
-- Looking for strnicmp - found
-- Looking for strchr
-- Looking for strchr - found
-- Looking for strdup
-- Looking for strdup - found
-- Looking for strrchr
-- Looking for strrchr - found
-- Looking for strstr
-- Looking for strstr - found
-- Looking for strtol
-- Looking for strtol - found
-- Looking for strtoul
-- Looking for strtoul - found
-- Looking for timegm
-- Looking for timegm - not found
-- Looking for towupper
-- Looking for towupper - found
-- Looking for towlower
-- Looking for towlower - found
-- Looking for mblen
-- Looking for mblen - found
-- Looking for wcsupr
-- Looking for wcsupr - found
-- Looking for wcslwr
-- Looking for wcslwr - found
-- Looking for wcsnicmp
-- Looking for wcsnicmp - found
-- Looking for wcsicmp
-- Looking for wcsicmp - found
-- Looking for C++ include cstdint
-- Looking for C++ include cstdint - found
-- Performing Test CSTDINT_FUNCTIONAL
-- Performing Test CSTDINT_FUNCTIONAL - Success
-- Looking for C++ include stdint.h
-- Looking for C++ include stdint.h - found
-- Looking for C++ include inttypes.h
-- Looking for C++ include inttypes.h - found
-- Check size of off_t
-- Check size of off_t - done
-- Check size of size_t
-- Check size of size_t - done
-- Check size of ssize_t
-- Check size of ssize_t - failed
-- Check size of wchar_t
-- Check size of wchar_t - done
-- Check size of signed short
-- Check size of signed short - done
-- Check size of unsigned short
-- Check size of unsigned short - done
-- Check size of signed int
-- Check size of signed int - done
-- Check size of unsigned int
-- Check size of unsigned int - done
-- Check size of signed long
-- Check size of signed long - done
-- Check size of unsigned long
-- Check size of unsigned long - done
-- Check size of signed long long
-- Check size of signed long long - done
-- Check size of unsigned long long
-- Check size of unsigned long long - done
-- Check size of __int64
-- Check size of __int64 - done
-- Check size of unsigned __int64
-- Check size of unsigned __int64 - done
-- Check size of unsigned char *
-- Check size of unsigned char * - done
-- Found the following ICU libraries:
--   uc (required)
-- The following ICU libraries were not found:
--   data (required)
-- Failed to find all ICU components (missing: ICU_INCLUDE_DIR _ICU_REQUIRED_LIBS_FOUND)
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - not found
-- Found Threads: TRUE
-- Performing Test XERCES_HAVE_STD_THREAD
-- Performing Test XERCES_HAVE_STD_THREAD - Success
-- Looking for C++ include winsock2.h
-- Looking for C++ include winsock2.h - found
-- Looking for C++ include nl_types.h
-- Looking for C++ include nl_types.h - not found
-- Looking for catopen
-- Looking for catopen - not found
-- Looking for catclose
-- Looking for catclose - not found
-- Looking for catgets
-- Looking for catgets - not found
-- Looking for C++ include iconv.h
-- Looking for C++ include iconv.h - not found
-- Looking for C++ include stdio.h
-- Looking for C++ include stdio.h - found
-- Looking for C++ include ctype.h
-- Looking for C++ include ctype.h - found
-- Looking for C++ include errno.h
-- Looking for C++ include errno.h - found
-- Looking for iconv_open
-- Looking for iconv_open - not found
-- Looking for iconv_close
-- Looking for iconv_close - not found
-- Looking for iconv
-- Looking for iconv - not found
-- Looking for wcstombs
-- Looking for wcstombs - found
-- Looking for mbstowcs
-- Looking for mbstowcs - found
-- Performing Test HAVE_STD_char16_t
-- Performing Test HAVE_STD_char16_t - Success
-- Check size of char16_t
-- Check size of char16_t - done
-- Performing Test WINDOWS_wchar
-- Performing Test WINDOWS_wchar - Success
-- Performing Test CXX_matching-delete-operator
-- Performing Test CXX_matching-delete-operator - Success
-- Performing Test HAVE_BOOL
-- Performing Test HAVE_BOOL - Success
-- Performing Test HAVE_CONST
-- Performing Test HAVE_CONST - Success
-- Performing Test CXX_HAS_inline
-- Performing Test CXX_HAS_inline - Success
-- Performing Test HAVE_VOLATILE
-- Performing Test HAVE_VOLATILE - Success
-- Performing Test HAVE_LSTRING
-- Performing Test HAVE_LSTRING - Success
-- Performing Test HAVE_NAMESPACES
-- Performing Test HAVE_NAMESPACES - Success
-- Performing Test HAVE_STD_LIBS
-- Performing Test HAVE_STD_LIBS - Success
-- Performing Test HAVE_STD_NAMESPACE
-- Performing Test HAVE_STD_NAMESPACE - Success
-- Performing Test XERCES_HAVE_INTRIN_H
-- Performing Test XERCES_HAVE_INTRIN_H - Success
-- Performing Test XERCES_HAVE_EMMINTRIN_H
-- Performing Test XERCES_HAVE_EMMINTRIN_H - Failed
-- Performing Test HAVE_CPUID_H
-- Performing Test HAVE_CPUID_H - Failed
-- Performing Test XERCES_HAVE_CPUID_INTRINSIC
-- Performing Test XERCES_HAVE_CPUID_INTRINSIC - Failed
-- Performing Test XERCES_HAVE_GETCPUID
-- Performing Test XERCES_HAVE_GETCPUID - Failed
-- Performing Test XERCES_HAVE_SSE2_INTRINSIC
-- Performing Test XERCES_HAVE_SSE2_INTRINSIC - Failed
-- Performing Test HAVE_PATH_MAX
-- Performing Test HAVE_PATH_MAX - Failed
-- Performing Test HAVE_MBRLEN
-- Performing Test HAVE_MBRLEN - Success
-- Performing Test HAVE_WCSRTOMBS
-- Performing Test HAVE_WCSRTOMBS - Success
-- Performing Test HAVE_MBSRTOWCS
-- Performing Test HAVE_MBSRTOWCS - Success
-- Performing Test ICONV_USES_CONST_POINTER
-- Performing Test ICONV_USES_CONST_POINTER - Failed
-- Could NOT find Java (missing: Java_JAVA_EXECUTABLE Runtime)
--
-- Xerces-C++ configuration summary
-- --------------------------------
--
--   Version:                   3.2.5
--   Library interface version: 3.2
--
--   Installation directory:    C:/Program Files (x86)/ParseXMLFC
--   C compiler:                C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.42.34226/bin/Hostarm64/arm64/cl.exe
--   C++ compiler:              C:/Program Files/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/14.42.34226/bin/Hostarm64/arm64/cl.exe
--
--   Build shared libraries:    ON
--   Path delimiters:           "/\"
--   File Manager:              windows
--   Mutex Manager:             standard
--   Transcoder:                windows
--   NetAccessor:               winsock
--   Message Loader:            inmemory
--   XMLCh type:                char16_t
-- !!! CMAKE_FIND_PACKAGE_REDIRECTS_DIR: C:/Users/adm/Desktop/cmake_tests/xerces_fetch_content/build/CMakeFiles/pkgRedirects/
-- !!! XercesC_INCLUDE_DIR:
-- !!! XercesC_LIBRARY:
-- !!! XercesC_LIBRARIES:
-- Configuring done (69.5s)
CMake Error at CMakeLists.txt:40 (target_link_libraries):
  Target "ParseXMLFC" links to:

    XercesC::XercesC

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

-- Generating done (0.2s)
CMake Generate step failed.  Build files cannot be regenerated correctly.

I guess this can’t work!

see xerces-c/src/XercesCConfig.cmake.in at master · apache/xerces-c · GitHub

Try to link xerces-c or install XercesC first!

The variables you are trying to reference (XercesC_INCLUDE_DIR and XercesC_LIBRARIES) are only defined if you use find_package(), not FetchContent (here I mean only if find_package() finds XercesC the normal way rather than being redirected to find it via FetchContent instead like you’re doing). But you shouldn’t need these variables anyway. You should just be able to link to the relevant CMake target and that should apply the header search paths and libraries to link transitively without any further action from you. Using variables is the old way, using targets is the new way (well, it’s been the “new way” for many years now).

Not all projects were written to expect being included directly in a build like with FetchContent. XercesC is probably old enough that it never considered being used that way. You could contact the XercesC folks to see if they are willing to update their CMake logic, but that’s probably not a short term solution. You could add those changes yourself in a fork, but that’s also not particularly good for anyone other than yourself. You could check if they define a CMake project by a different name that you could link to, and that’s probably your most promising avenue. I have no real familiarity with XercesC, so you’d need to go digging through its CMake logic to find a suitable target yourself.

I use Xerces-C this way in the project. The target that works is xerces-c.

BTW: I also patch the its CMakeLists.txt to remove building of doc, tests, and samples subdirectories as there’s no option to do this.

2 Likes

I would use

if(NOT TARGET XercesC::XercesC)
    add_library(XercesC::XercesC ALIAS xerces-c)
endif()

to be flexible, if XercesC is already installed.

Yeah, that should work.
@ClausKlein’s post is also a good tip.

Sorry, I’m obviously missing something here.

I can get the link to work using xerces-c - thankyou:

target_link_libraries(
         ${PROJECT_NAME}
         PRIVATE
         xerces-c <--- this now links
         fmt::fmt-header-only
 )

But there are no xerces include directories set, how does the preprocessor find the header files, in my code?

....
#include <fmt/core.h>
#include <chrono>
#include <xercesc/util/PlatformUtils.hpp>  <---- not found
#include <xercesc/dom/DOMErrorHandler.hpp> <---- not found
....

Damn!
So, apparently, this is why we have this piece of code after FetchContent:

# xerces doesn't seem to carry include directories. This is an error on the xerces side
get_target_property(_inc_dir xerces-c INCLUDE_DIRECTORIES)
target_include_directories(xerces-c SYSTEM BEFORE INTERFACE "$<BUILD_INTERFACE:${_inc_dir}>")

Interesting and weird.

ahh ok that makes sense and works - thanks.

We have three options to use xerces, prebuilt/installed, fetched or via a package manager.

I think we are now swaying towards either prebuilt or package manager, as this all seems a bit of a nonsense of magic that’ll be instantly forgot.

Many thanks