Crascit/DownloadProject

Add mention of CMake 3.11 FetchContent

Closed this issue · 10 comments

A similar tool was just added to CMake 3.11: the FetchContent module, which downloads content at configure time. I would recommend adding a mention of this module to the README just in case a user is okay with requiring CMake 3.11+.

Yep, I was the one who added the FetchContent module to CMake. ;)

Updating DownloadProject to forward to FetchContent if available and updating various other blogs, stackoverflow comments, etc. is on my todo list.

I guessed as much :)

And, since you are updating examples, I've found that the following is ideal for adding googletest:

# CMake warning suppression will not be needed in version 1.9 if ever released
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "")
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS)

The warning suppression is only needed if you use CMake's VERSION option in the main project. The EXCLUDE_FROM_ALL had something to do with the export set when installing, I think; IIRC it keeps google test from installing itself when you make install; it still builds when you use a google test target.

We are currently using something like the following to address that and a couple of other shortcomings:

    set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)

    # Needed because googletest project sets minimum CMake version < 3.0
    set(CMAKE_POLICY_DEFAULT_CMP0048 OLD)

    # Ignore undef warnings, issue with source file:
    # googletest/include/gtest/internal/gtest-port.h:309:5: error: "_MSC_VER" is not defined
    if(NOT MSVC)
        add_compile_options( -Wno-undef )
    endif()

    # Prevent GoogleTest from overriding our compiler/linker options
    # when building with Visual Studio
    set(gtest_force_shared_crt ON CACHE INTERNAL "")
    set(BUILD_SHARED_LIBS OFF)

    set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME googletest)
    add_subdirectory("${googletest_SOURCE_DIR}" "${googletest_BINARY_DIR}")

We always do this in its own directory scope to ensure that whatever we need to do for this dependency, it is isolated from anything else in the project, so no need to undo changes we make to policies, variables, etc.

The EXCLUDE_FROM_ALL option to add_subdirectory() doesn't play nice with some combinations of CMake version and generator type (notably Xcode, not sure which CMake versions). Setting the directory property I think avoids those issues, from what I recall. Setting CMAKE_INSTALL_DEFAULT_COMPONENT_NAME was ultimately a better solution for us because we always do component-based installs and we just always omit the googletest component in our packages.

unset() won't delete a cache variable unless you give it the CACHE keyword. If you set CMAKE_SUPPRESS_DEVELOPER_WARNINGS, I'm guessing it probably doesn't need to be a cache variable anyway.

Thanks for the tips! I regularly use Xcode, and haven't had a problem with the EXCLUDE_FROM_ALL on add_subdirectory; on macOS, it's pretty easy (and necessary) to keep a modern CMake version (homebrew is usually only a few minutes behind cmake.org).

On Windows, I also need:

if(MSVC AND MSVC_VERSION GREATER_EQUAL 1900)
    target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
    target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
    target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
    target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif()

This allows GTest 1.8.0 to build on MSVC 2017, unless it's in C++17 mode (which won't work at all). Looking forward to the upcoming 1.8.1 release!

I have an "AddGTest.cmake" script, and a chapter on GTest in Modern CMake; I'll be updating them with your suggestions once I play with them a bit.

Mizux commented

My 2cents, according to CMake documentation

Installing a target with the EXCLUDE_FROM_ALL target property set to TRUE has undefined behavior.

src: https://cmake.org/cmake/help/latest/command/install.html#targets

Hey folks, I have a question. Neither this approach nor FetchContent works for flatcc library. All because flatcc doesn't follow the natural way/patter of CMake build system. You have to run a separate script scripts/build.sh to build it.

I am new to CMake and I tried different approaches, methods, and I tried to modify this code to make flatcc to build in the right way, but all my tries were futile due to lack of experience with CMake.

Is there an easy way to make flatcc library work with FetchContent or add custom build command to ExternalProject_Add function?

You can specify a BUILD_COMMAND, maybe the docs would be useful but I'm not quite sure if they are.

Is there an easy way to make flatcc library work with FetchContent or add custom build command to ExternalProject_Add function?

Not for FetchContent, but as @Frenzie mentioned, you can specify BUILD_COMMAND with ExternalProject_Add() to make its build step do anything you want. If you can work out a command line that would build flatcc (which it looks like you already have, judging by the .travis.yml file), then you should be able to use it or something close to it as the BUILD_COMMAND.

@audiofanatic yes, thanks for the tips!

This repository is no longer maintained. I updated the "About" and URL for the repo to redirect the user to CMake's FetchContent module instead.