Search code examples
windowscmakeopenssl64-bitexternal-project

When does ExternalProject_Add build?


I want to build openssl and link my project against it. In my project, I have a library called net which is the part that uses openssl. So in my net\CMakeList, I added

include_directories(
    ../
  + ../../../ext/openssl/inc32/
)
add_library(net STATIC ${sources})
+ ADD_DEPENDENCIES(net openssl)

In my ext folder that is used for organizing all external library, I have a fresh unzipped openssl source code in a folder named openssl. Then I edited ext\CmakeList

message(STATUS "Configuring OpenSSL")
set(openssl_dir openssl)
if (CMAKE_CL_64)
include(ExternalProject)

set(OPENSSL_CONFIGURE perl\ Configure\ VC-WIN64A)
set(OPENSSL_MAKE  ms\\do_win64a\ &&\ nmake\ -f\ ms\\ntdll.mak)

ExternalProject_Add(openssl
    PREFIX openssl
    #-- Download Step ----------
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/ext/openssl
    #--Configure step ----------
        CONFIGURE_COMMAND ${OPENSSL_CONFIGURE}
    #--Build Step ----------
    BUILD_COMMAND ${OPENSSL_MAKE}
    BUILD_IN_SOURCE 1
    #--install Step ----------
    INSTALL_COMMAND ""} 
)

endif()

When I built, the compiler complained the it can't find include files, and the openssl source code was not built at all, since there is no out32dll and inc32.

My question is: When does ExternalProject_Add actually build the project? If I make my net library depending on openssl, does it mean when I build net it would need to check and build openssl first?


Solution

  • Install missed

    First of all I think you missed an install step. See documentation:

    nmake -f "ms\ntdll.mak" install

    So simplified version of ExternalProject_Add is:

    ExternalProject_Add(
        OpenSSL
        URL https://github.com/openssl/openssl/archive/OpenSSL_1_0_1h.tar.gz
        CONFIGURE_COMMAND perl Configure VC-WIN64A "--prefix=${CMAKE_INSTALL_PREFIX}"
        BUILD_COMMAND "ms\\do_win64a.bat"
        COMMAND nmake -f "ms\\ntdll.mak"
        BUILD_IN_SOURCE 1
        INSTALL_COMMAND nmake -f "ms\\ntdll.mak" install
    )
    

    Find OpenSSL

    Second, if you want to find openssl libraries and headers, you need to use find_package(OpenSSL) command:

    find_package(OpenSSL REQUIRED)
    message("Libs: ${OPENSSL_LIBRARIES}")
    message("Includes: ${OPENSSL_INCLUDE_DIR}")
    

    Builds

    Now, if you put all this commands together in one project configure step will fail :) Because it's not how ExternalProject designed. Superbuild that made by few or one ExternalProject_Add commands must be configured first, then build step will install the libraries from external archives. This will conflict with your project, because openssl libraries can't be found - they are not installed by superbuild yet.

    Fix

    Split cmake code. Run superbuild first (i.e. download and install openssl):

    > cmake -Hsuperbuild -B_builds\superbuild "-GVisual Studio 12 2013 Win64" -DCMAKE_INSTALL_PREFIX=ext\install
    # note, no ext\install directory yet
    > cmake --build _builds\superbuild
    # install done, libraries can be found in ext\install
    

    Then build your project, note that the libraries found on configure step:

    > cmake -Huse -B_builds\use "-GVisual Studio 12 2013 Win64" -DCMAKE_INSTALL_PREFIX=ext\install
    -- Found OpenSSL: .../ext/install/lib/ssleay32.lib;.../ext/install/lib/libeay32.lib (found version "1.0.1h")
    Libs: .../ext/install/lib/ssleay32.lib;.../ext/install/lib/libeay32.lib
    Includes: .../ext/install/include
    > cmake --build _builds\use
    # OK
    

    Experimental

    I have an experimental project that wrap all of this noise in one command (Windows tested on Visual Studio 2013):

    hunter_add_package(OpenSSL)
    find_package(OpenSSL REQUIRED)