Search code examples
c++cmakexercesxerces-c

add preprocessor define to cmake external project


I would like to build xerces-c as a static library on windows using a cmake ExternalProject. However, for this to work I'd need add the XERCES_STATIC_LIBRARY preprocessor definition to the project. On linux, it seems like I can do it easily enough with a patch file, but I'm not sure how to go about doing this on windows.

Here's my current CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
PROJECT(xercesc)
SET(TARGET_NAME xercesc)

IF(WIN32)
    # find the msvc version
    if(${MSVC_VERSION} EQUAL 1400)
        SET(VC_PROJ_DIR VC8)
    elseif(${MSVC_VERSION} EQUAL 1500)
        SET(VC_PROJ_DIR VC9)
    elseif(${MSVC_VERSION} EQUAL 1600)
        SET(VC_PROJ_DIR VC10)
    elseif(${MSVC_VERSION} EQUAL 1700)
        SET(VC_PROJ_DIR VC11)
    elseif(${MSVC_VERSION} EQUAL 1800)
        SET(VC_PROJ_DIR VC12)
    endif(${MSVC_VERSION} EQUAL 1400)

    include(ExternalProject)
    ExternalProject_Add(
      ${TARGET_NAME}
      URL ${CMAKE_CURRENT_SOURCE_DIR}/xerces-c-${XERCESC_VERSION}.tar.gz
      DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xercesc
      SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xercesc
      CONFIGURE_COMMAND ""
      BUILD_COMMAND Devenv "${CMAKE_CURRENT_SOURCE_DIR}/xercesc/projects/Win32/${VC_PROJ_DIR}/xerces-all/xerces-all.sln" /build Release
      INSTALL_COMMAND ""
      BUILD_IN_SOURCE 1
    )
ENDIF(WIN32)

Solution

  • switching from Devenv to the msbuild command line the secret-sauce. It's much more powerful, and you can define constants using /property:DefineConstants=XERCES_STATIC_LIBRARY. BEWARE: it will blow away other constants defined in the project files... but you wouldn't be silly enough to define constants in a .vcxproj file in a cmake build, would you?

    So anyway, here's the full solution to build xerces-c on windows. Notice, for a static build, they use (God forsaken) spaces in their configuration name. The simplest fix is to replace them with underscores and move on with life. I used the find and replace text (FART) tool.

    Also, I was doing a DLL runtime library build, so I replaced all the /MT options.

    cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
    PROJECT(xercesc)
    SET(TARGET_NAME xercesc)
    
    IF(WIN32)
        # find the msvc version
        if(${MSVC_VERSION} EQUAL 1400)
            SET(VC_PROJ_DIR VC8)
        elseif(${MSVC_VERSION} EQUAL 1500)
            SET(VC_PROJ_DIR VC9)
        elseif(${MSVC_VERSION} EQUAL 1600)
            SET(VC_PROJ_DIR VC10)
        elseif(${MSVC_VERSION} EQUAL 1700)
            SET(VC_PROJ_DIR VC11)
        elseif(${MSVC_VERSION} EQUAL 1800)
            SET(VC_PROJ_DIR VC12)
        endif(${MSVC_VERSION} EQUAL 1400)
    
        # Use FART to replace spaces in the project files, ugh. FART requires windows style slashes.
        SET(XERCES_SOLUTION_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xercesc/projects/Win32/${VC_PROJ_DIR}/xerces-all)   
        SET(XERCES_SOLUTION "${XERCES_SOLUTION_DIR}/xerces-all.sln")
        SET(XERCES_SOLUTIONS "${XERCES_SOLUTION_DIR}/*.sln")
        SET(XERCES_PROJECTS "${XERCES_SOLUTION_DIR}/*.vcxproj")
        SET(XERCES_LIB_PROJECT "${XERCES_SOLUTION_DIR}/XercesLib/XercesLib.vcxproj")
        STRING(REGEX REPLACE "/" "\\\\" XERCES_SOLUTIONS_WIN ${XERCES_SOLUTIONS})
        STRING(REGEX REPLACE "/" "\\\\" XERCES_PROJECTS_WIN ${XERCES_PROJECTS})
    
        include(ExternalProject)
        ExternalProject_Add(
            ${TARGET_NAME}
            DEPENDS fart
            URL ${CMAKE_CURRENT_SOURCE_DIR}/xerces-c-${XERCESC_VERSION}.tar.gz
            DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xercesc
            SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xercesc
            PATCH_COMMAND ${FART_DIR}/bin/$<CONFIGURATION>/fart.exe -v -r --svn -- ${XERCES_SOLUTIONS_WIN},${XERCES_PROJECTS_WIN} "Static " Static_ 
            COMMAND ${FART_DIR}/bin/$<CONFIGURATION>/fart.exe -v -r --svn -- ${XERCES_SOLUTIONS_WIN},${XERCES_PROJECTS_WIN} <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
            COMMAND ${FART_DIR}/bin/$<CONFIGURATION>/fart.exe -v -r --svn -- ${XERCES_SOLUTIONS_WIN},${XERCES_PROJECTS_WIN} <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
            CONFIGURE_COMMAND ""
            BUILD_COMMAND msbuild ${XERCES_LIB_PROJECT} /m /property:Configuration=Static_Release,Platform=x64 /property:DefineConstants=XERCES_STATIC_LIBRARY
            COMMAND msbuild ${XERCES_LIB_PROJECT} /m /property:Configuration=Static_Debug,Platform=x64 /property:DefineConstants=XERCES_STATIC_LIBRARY /property:DefineDebug=true
            INSTALL_COMMAND ""
            BUILD_IN_SOURCE 1
        )
        SET(LIBRARIES debug ${CMAKE_CURRENT_SOURCE_DIR}/xercesc/Build/Win64/${VC_PROJ_DIR}/Static_Debug/xerces-c_static_3D.lib)
        SET(LIBRARIES ${LIBRARIES} optimized ${CMAKE_CURRENT_SOURCE_DIR}/xercesc/Build/Win64/${VC_PROJ_DIR}/Static_Release/xerces-c_static_3.lib)
        SET(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/xercesc/src/)
    
    ELSE(WIN32)