noloader / cryptopp-cmake

CMake files for Crypto++ project
BSD 3-Clause "New" or "Revised" License
92 stars 68 forks source link

Question: Using FetchContent_Declare() with FetchContent_GetProperties() #58

Closed CleanHit closed 4 years ago

CleanHit commented 4 years ago

Since most of the CMakeLists files in the Crypto++ repository end with an answer that it was a failed experiment I try my luck here. My project uses the SEAL library and if I use this CMakeLists with Crypto++ then it somehow messes with the seal header files.

I use CLion on Fedora 32 and my goal is to be able to use

#include <secblock.h>
using secure_string = std::basic_string<char, std::char_traits<char>, CryptoPP::AllocatorWithCleanup<char>>;

In my project. Is it possible to import Crypto++ as an INTERFACE using:

# Get the cryptopp package
set(CRYPTOPP "cryptopp")
FetchContent_Declare(
        ${CRYPTOPP}
        GIT_REPOSITORY  https://github.com/weidai11/cryptopp
        GIT_TAG         CRYPTOPP_8_2_0
)

FetchContent_GetProperties(${CRYPTOPP})
if(NOT ${CRYPTOPP}_POPULATED)
    FetchContent_Populate(${CRYPTOPP})

    # Temporal as long as the project doesn't include CMakeLists.txt in a proper way. If that changes use:
    #add_subdirectory(${${CRYPTOPP}_SOURCE_DIR} ${${CRYPTOPP}_BINARY_DIR})
endif()

# The next two lines are Temporal as long as the project doesn't include CMakeLists.txt in a proper way:
#include_directories(${${CRYPTOPP}_BINARY_DIR})
add_library(${CRYPTOPP} INTERFACE)
target_include_directories(${CRYPTOPP} INTERFACE ${${CRYPTOPP}_SOURCE_DIR})

# Link the project libraries to the executable
target_link_libraries(my_project PRIVATE
    ${CRYPTOPP}
)

I'm not sure if I'll need to add:

add_executable(my_project
    ${${CRYPTOPP}_SOURCE_DIR}/<some header or source files>
)
target_link_libraries(my_project PRIVATE
    ${CRYPTOPP}
)

I'm asking because this doesn't work for Crypto++ but has worked for me with a different library that also doesn't use CMakeLists.txt file e.g.:

# Get the tinyfiledialogs package
set(TINY_FILE_DIALOGS "tinyfiledialogs")
FetchContent_Declare(
        ${TINY_FILE_DIALOGS}
        GIT_REPOSITORY  https://git.code.sf.net/p/tinyfiledialogs/code
        GIT_TAG         87597a # v3.6.3
)
FetchContent_GetProperties(${TINY_FILE_DIALOGS})
if(NOT ${TINY_FILE_DIALOGS}_POPULATED)
    FetchContent_Populate(${TINY_FILE_DIALOGS})
    # Temporal as long as the project doesn't include CMakeLists.txt in a proper way. If that changes use:
    #add_subdirectory(${${TINY_FILE_DIALOGS}_SOURCE_DIR} ${${TINY_FILE_DIALOGS}_BINARY_DIR})
endif()
# The next two lines are Temporal as long as the project doesn't include CMakeLists.txt in a proper way:
#include_directories(${${TINY_FILE_DIALOGS}_BINARY_DIR})
add_library(${TINY_FILE_DIALOGS} INTERFACE)
target_include_directories(${TINY_FILE_DIALOGS} INTERFACE ${${TINY_FILE_DIALOGS}_SOURCE_DIR})

add_executable(my_project
    ${${TINY_FILE_DIALOGS}_SOURCE_DIR}/tinyfiledialogs.c
)
target_link_libraries(my_project PRIVATE
    ${TINY_FILE_DIALOGS}
)
CleanHit commented 4 years ago

I've tried it again with the CMakeLists.txt file from this repository for some reason it doesn't collide with SEAL headers any more but the build fails anyway. What I did was:

  1. Fetch CRYPT++ with:
    # Get the cryptopp package
    set(CRYPTOPP "cryptopp")
    FetchContent_Declare(
        ${CRYPTOPP}
        GIT_REPOSITORY  https://github.com/weidai11/cryptopp
        GIT_TAG         CRYPTOPP_8_2_0
    )
    FetchContent_GetProperties(${CRYPTOPP})
    if(NOT ${CRYPTOPP}_POPULATED)
    FetchContent_Populate(${CRYPTOPP})
    endif()
  2. Copy the CMakeLists.txt file from this repository with TAG CRYPTOPP_8_2_0 into ${${CRYPTOPP}_SOURCE_DIR}.
  3. Use the copied CMakeLists.txt with:
    
    add_subdirectory(${${CRYPTOPP}_SOURCE_DIR} ${${CRYPTOPP}_BINARY_DIR})
    include_directories(${${CRYPTOPP}_SOURCE_DIR})

Link the project libraries to the executable

target_link_libraries(my_project PRIVATE ${CRYPTOPP} )

4. Use the rebuild project option from __CLion__

But I keep getting the error:
```bash
/usr/bin/ld: cannot find -lcryptopp
collect2: error: ld returned 1 exit status

My ${${CRYPTOPP}_BINARY_DIR} folder has the libcryptopp.a, libcryptopp.so and libcryptopp.so.8.2 files.

CleanHit commented 4 years ago

OK I've got it working by adding

set(CRYPTOPP_LIB ${${CRYPTOPP}_BINARY_DIR}/libcryptopp.so) # For a shared library variant

Then I've changed my ${CRYPTOPP} to ${CRYPTOPP_LIB} in target_link_libraries(). I wonder if there is a better way to achieve what I've done so far?

Next step is to try using FetchContent_Declare() and FetchContent_GetProperties() with this repository then adding a File(COPY....) command for the CMakeLists.txt file into ${${CRYPTOPP}_SOURCE_DIR}, right before executing

add_subdirectory(${${CRYPTOPP}_SOURCE_DIR} ${${CRYPTOPP}_BINARY_DIR})
include_directories(${${CRYPTOPP}_SOURCE_DIR})
CleanHit commented 4 years ago

Here is my solution using Linux (Fedora 32), if someone else will ever need it.

# Get the cryptopp CMakeLists.txt file for cryptopp package GIT_TAG must be the same
set(CRYPTOPP_CMAKE "cryptopp-cmake")
set(CRYPTOPP_GIT_TAG "CRYPTOPP_8_2_0")
FetchContent_Declare(
        ${CRYPTOPP_CMAKE}
        GIT_REPOSITORY  https://github.com/noloader/cryptopp-cmake
        GIT_TAG         ${CRYPTOPP_GIT_TAG}
)

FetchContent_GetProperties(${CRYPTOPP_CMAKE})
if(NOT ${CRYPTOPP_CMAKE}_POPULATED)
    FetchContent_Populate(${CRYPTOPP_CMAKE})
endif()

# Get the cryptopp package
set(CRYPTOPP "cryptopp")
FetchContent_Declare(
        ${CRYPTOPP}
        GIT_REPOSITORY  https://github.com/weidai11/cryptopp
        GIT_TAG         ${CRYPTOPP_GIT_TAG}
)

FetchContent_GetProperties(${CRYPTOPP})
if(NOT ${CRYPTOPP}_POPULATED)
    FetchContent_Populate(${CRYPTOPP})
    # !!! IMPORTANT !!!
    # Copy the CMakeLists.txt into ${${CRYPTOPP}_SOURCE_DIR}
    # before using add_subdirectory() and include_directories() commands.
    file(COPY ${${CRYPTOPP_CMAKE}_SOURCE_DIR}/CMakeLists.txt DESTINATION ${${CRYPTOPP}_SOURCE_DIR})
    add_subdirectory(${${CRYPTOPP}_SOURCE_DIR} ${${CRYPTOPP}_BINARY_DIR})
endif()
include_directories(${${CRYPTOPP}_SOURCE_DIR})
# Set Cryptopp library properties
if(${CRYPTOPP}_POPULATED)
    if(${BUILD_SHARED} STREQUAL "ON")
        set(CRYPTOPP_SHARED "cryptopp-shared")
    endif()
    if(${BUILD_STATIC} STREQUAL "ON")
        set(CRYPTOPP_STATIC "cryptopp-static")
    endif()
endif()

# Link the Crypto++ library to the main project
target_link_libraries(hmmenc-client PRIVATE
        ${CRYPTOPP_STATIC}  # Crypto++ static lib
        #${CRYPTOPP_SHARED} # Crypto++ shared lib
)