Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cmake option to skip building mock libraries #13673

Merged
merged 3 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,28 @@ This option is required to support package maintainers that split
OFF)
mark_as_advanced(GOOGLE_CLOUD_CPP_USE_INSTALLED_COMMON)

include(CMakeDependentOption)
cmake_dependent_option(
GOOGLE_CLOUD_CPP_WITH_MOCKS
[==[Build the google-cloud-cpp mocking libraries.

google-cloud-cpp offers mocking libraries with mock classes, to facilitate unit
testing of Cloud C++ clients. Consumers of this library that do not use the
provided mocks to test code involving the Cloud C++ clients may wish to turn
this flag off.]==]
ON
"NOT BUILD_TESTING"
ON)
mark_as_advanced(GOOGLE_CLOUD_CPP_WITH_MOCKS)
Comment on lines +169 to +180
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL, you can use NOT condition in cmake_dependent_option. Using ON ... ON looks weird. I think you want something like this:

Suggested change
cmake_dependent_option(
GOOGLE_CLOUD_CPP_WITH_MOCKS
[==[Build the google-cloud-cpp mocking libraries.
google-cloud-cpp offers mocking libraries with mock classes, to facilitate unit
testing of Cloud C++ clients. Consumers of this library that do not use the
provided mocks to test code involving the Cloud C++ clients may wish to turn
this flag off.]==]
ON
"NOT BUILD_TESTING"
ON)
mark_as_advanced(GOOGLE_CLOUD_CPP_WITH_MOCKS)
option(
GOOGLE_CLOUD_CPP_WITH_MOCKS
[==[Build the google-cloud-cpp mocking libraries.
google-cloud-cpp offers mocking libraries with mock classes, to facilitate unit
testing of Cloud C++ clients. Consumers of this library that do not use the
provided mocks to test code involving the Cloud C++ clients may wish to turn
this flag off.]==]
$<IF:$<BOOL:${BUILD_TESTING}>:OFF:ON>)
mark_as_advanced(GOOGLE_CLOUD_CPP_WITH_MOCKS)

That is, the option always exists, but its default value is based on a generator expression.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I want that.

The default value should always be ON, regardless of BUILD_TESTING. But if BUILD_TESTING is ON, then GOOGLE_CLOUD_CPP_WITH_MOCKS must be ON (because our unit tests depend on the mock libraries). That is what I am enforcing with the ON ... ON.

I think this is doing what I want. Adding a debug print statement after the option is defined:

$ cmake -DBUILD_TESTING=ON -DGOOGLE_CLOUD_CPP_WITH_MOCKS=OFF
GOOGLE_CLOUD_CPP_WITH_MOCKS=ON

$ cmake -DBUILD_TESTING=OFF -DGOOGLE_CLOUD_CPP_WITH_MOCKS=OFF
GOOGLE_CLOUD_CPP_WITH_MOCKS=OFF
$ cmake -LAH
...

// Build the google-cloud-cpp mocking libraries.

google-cloud-cpp offers mocking libraries with mock classes, to facilitate unit
testing of Cloud C++ clients. Consumers of this library that do not use the
provided mocks to test code involving the Cloud C++ clients may wish to turn
this flag off.
GOOGLE_CLOUD_CPP_WITH_MOCKS:BOOL=ON


# The examples use exception handling to simplify the code. Therefore they
# cannot be compiled when exceptions are disabled, and applications cannot force
# the flag.
cmake_dependent_option(
GOOGLE_CLOUD_CPP_ENABLE_EXAMPLES "Compile the google-cloud-cpp examples."
ON "GOOGLE_CLOUD_CPP_ENABLE_CXX_EXCEPTIONS;BUILD_TESTING" OFF)
mark_as_advanced(GOOGLE_CLOUD_CPP_ENABLE_EXAMPLES)

include(GoogleCloudCppFeatures)

# Controls the list of features compiled by `google-cloud-cpp`.
Expand Down Expand Up @@ -231,14 +253,6 @@ if (BUILD_TESTING)
include(FindGMockWithTargets)
endif ()

# The examples use exception handling to simplify the code. Therefore they
# cannot be compiled when exceptions are disabled, and applications cannot force
# the flag.
cmake_dependent_option(
GOOGLE_CLOUD_CPP_ENABLE_EXAMPLES "Compile the google-cloud-cpp examples."
ON "GOOGLE_CLOUD_CPP_ENABLE_CXX_EXCEPTIONS;BUILD_TESTING" OFF)
mark_as_advanced(GOOGLE_CLOUD_CPP_ENABLE_EXAMPLES)

# Add any subdirectories configured in the application.

# `docfx/` must be included before any library directories. The tool is used to
Expand Down
66 changes: 34 additions & 32 deletions cmake/GoogleCloudCppLibrary.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -253,37 +253,6 @@ function (google_cloud_cpp_add_gapic_library library display_name)

add_library(${library_alias} ALIAS ${library_target})

# Create a header-only library for the mocks. We use a CMake `INTERFACE`
# library for these, a regular library would not work on macOS (where the
# library needs at least one .o file). Unfortunately INTERFACE libraries are
# a bit weird in that they need absolute paths for their sources.
file(
GLOB relative_mock_files
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${mocks_globs})
list(SORT relative_mock_files)
set(mock_files)
foreach (file IN LISTS relative_mock_files)
# We use a generator expression per the recommendation in:
# https://stackoverflow.com/a/62465051
list(APPEND mock_files
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${file}>")
endforeach ()
add_library(${mocks_target} INTERFACE)
target_sources(${mocks_target} INTERFACE ${mock_files})
target_link_libraries(
${mocks_target} INTERFACE ${library_alias} GTest::gmock_main
GTest::gmock GTest::gtest)
set_target_properties(${mocks_target} PROPERTIES EXPORT_NAME
${library_alias}_mocks)
target_include_directories(
${mocks_target}
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
target_compile_options(${mocks_target}
INTERFACE ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG})

# Get the destination directories based on the GNU recommendations.
include(GNUInstallDirs)

Expand Down Expand Up @@ -349,7 +318,40 @@ function (google_cloud_cpp_add_gapic_library library display_name)
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${library_target}"
COMPONENT google_cloud_cpp_development)

google_cloud_cpp_install_mocks("${library}" "${display_name}")
if (GOOGLE_CLOUD_CPP_WITH_MOCKS)
# Create a header-only library for the mocks. We use a CMake `INTERFACE`
# library for these, a regular library would not work on macOS (where
# the library needs at least one .o file). Unfortunately INTERFACE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action needed: I wonder if this is still true now that we use CMake >= 3.13 ..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, I don't know the answer and I don't have easy access to a mac.

# libraries are a bit weird in that they need absolute paths for their
# sources.
file(
GLOB relative_mock_files
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
${mocks_globs})
list(SORT relative_mock_files)
set(mock_files)
foreach (file IN LISTS relative_mock_files)
# We use a generator expression per the recommendation in:
# https://stackoverflow.com/a/62465051
list(APPEND mock_files
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${file}>")
endforeach ()
add_library(${mocks_target} INTERFACE)
target_sources(${mocks_target} INTERFACE ${mock_files})
target_link_libraries(
${mocks_target} INTERFACE ${library_alias} GTest::gmock_main
GTest::gmock GTest::gtest)
set_target_properties(${mocks_target} PROPERTIES EXPORT_NAME
${library_alias}_mocks)
target_include_directories(
${mocks_target}
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
target_compile_options(${mocks_target}
INTERFACE ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG})
google_cloud_cpp_install_mocks("${library}" "${display_name}")
endif ()

# ${library_alias} must be defined before we can add the samples.
if (BUILD_TESTING AND GOOGLE_CLOUD_CPP_ENABLE_CXX_EXCEPTIONS)
Expand Down
153 changes: 79 additions & 74 deletions google/cloud/bigquery/bigquery_rest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -162,37 +162,90 @@ target_compile_options(google_cloud_cpp_bigquery_rest
add_library(google-cloud-cpp::experimental-bigquery_rest ALIAS
google_cloud_cpp_bigquery_rest)

# Create a header-only library for the mocks.
add_library(google_cloud_cpp_bigquery_rest_mocks INTERFACE)
target_sources(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_dataset_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_job_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_project_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_table_connection.h)
target_link_libraries(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE google-cloud-cpp::experimental-bigquery_rest GTest::gmock_main
GTest::gmock GTest::gtest)
set_target_properties(
google_cloud_cpp_bigquery_rest_mocks
PROPERTIES EXPORT_NAME google-cloud-cpp::experimental-bigquery_rest_mocks)
target_include_directories(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
target_compile_options(google_cloud_cpp_bigquery_rest_mocks
INTERFACE ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG})
add_library(google-cloud-cpp::experimental-bigquery_rest_mocks ALIAS
google_cloud_cpp_bigquery_rest_mocks)
# Get the destination directories based on the GNU recommendations.
include(GNUInstallDirs)

# Export the CMake targets to make it easy to create configuration files.
install(
EXPORT google_cloud_cpp_bigquery_rest-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_bigquery_rest"
COMPONENT google_cloud_cpp_development)

# Install the libraries and headers in the locations determined by
# GNUInstallDirs
install(
TARGETS google_cloud_cpp_bigquery_rest
EXPORT google_cloud_cpp_bigquery_rest-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT google_cloud_cpp_runtime
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT google_cloud_cpp_runtime
NAMELINK_COMPONENT google_cloud_cpp_development
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT google_cloud_cpp_development)

google_cloud_cpp_install_headers("google_cloud_cpp_bigquery_rest"
"include/google/cloud/bigquery")

google_cloud_cpp_add_pkgconfig(
bigquery_rest "Experimental BigQuery REST client library"
"An experimental BigQuery C++ client library using REST for transport."
"google_cloud_cpp_rest_internal")

# Create and install the CMake configuration files.
include(CMakePackageConfigHelpers)
configure_file("config-rest.cmake.in"
"google_cloud_cpp_bigquery_rest-config.cmake" @ONLY)
write_basic_package_version_file(
"google_cloud_cpp_bigquery_rest-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY ExactVersion)

install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_bigquery_rest-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_bigquery_rest-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_bigquery_rest"
COMPONENT google_cloud_cpp_development)

if (GOOGLE_CLOUD_CPP_WITH_MOCKS)
# Create a header-only library for the mocks.
add_library(google_cloud_cpp_bigquery_rest_mocks INTERFACE)
target_sources(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_dataset_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_job_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_project_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/v2/minimal/mocks/mock_table_connection.h
)
target_link_libraries(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE google-cloud-cpp::experimental-bigquery_rest
GTest::gmock_main GTest::gmock GTest::gtest)
set_target_properties(
google_cloud_cpp_bigquery_rest_mocks
PROPERTIES EXPORT_NAME
google-cloud-cpp::experimental-bigquery_rest_mocks)
target_include_directories(
google_cloud_cpp_bigquery_rest_mocks
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
target_compile_options(google_cloud_cpp_bigquery_rest_mocks
INTERFACE ${GOOGLE_CLOUD_CPP_EXCEPTIONS_FLAG})
add_library(google-cloud-cpp::experimental-bigquery_rest_mocks ALIAS
google_cloud_cpp_bigquery_rest_mocks)
create_bazel_config(google_cloud_cpp_bigquery_rest_mocks YEAR "2023")

google_cloud_cpp_install_headers("google_cloud_cpp_bigquery_rest_mocks"
"include/google/cloud/bigquery")
endif ()

# To avoid maintaining the list of files for the library, export them to a .bzl
# file.
include(CreateBazelConfig)
create_bazel_config(google_cloud_cpp_bigquery_rest YEAR "2023")
create_bazel_config(google_cloud_cpp_bigquery_rest_mocks YEAR "2023")

# Define the tests in a function so we have a new scope for variable names.
function (bigquery_rest_define_tests)
Expand Down Expand Up @@ -316,54 +369,6 @@ function (bigquery_rest_define_tests)
endforeach ()
endfunction ()

# Get the destination directories based on the GNU recommendations.
include(GNUInstallDirs)

# Export the CMake targets to make it easy to create configuration files.
install(
EXPORT google_cloud_cpp_bigquery_rest-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_bigquery_rest"
COMPONENT google_cloud_cpp_development)

# Install the libraries and headers in the locations determined by
# GNUInstallDirs
install(
TARGETS google_cloud_cpp_bigquery_rest
EXPORT google_cloud_cpp_bigquery_rest-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT google_cloud_cpp_runtime
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT google_cloud_cpp_runtime
NAMELINK_COMPONENT google_cloud_cpp_development
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT google_cloud_cpp_development)

google_cloud_cpp_install_headers("google_cloud_cpp_bigquery_rest"
"include/google/cloud/bigquery")
google_cloud_cpp_install_headers("google_cloud_cpp_bigquery_rest_mocks"
"include/google/cloud/bigquery")

google_cloud_cpp_add_pkgconfig(
bigquery_rest "Experimental BigQuery REST client library"
"An experimental BigQuery C++ client library using REST for transport."
"google_cloud_cpp_rest_internal")

# Create and install the CMake configuration files.
include(CMakePackageConfigHelpers)
configure_file("config-rest.cmake.in"
"google_cloud_cpp_bigquery_rest-config.cmake" @ONLY)
write_basic_package_version_file(
"google_cloud_cpp_bigquery_rest-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY ExactVersion)

install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_bigquery_rest-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/google_cloud_cpp_bigquery_rest-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/google_cloud_cpp_bigquery_rest"
COMPONENT google_cloud_cpp_development)

if (BUILD_TESTING)
bigquery_rest_define_tests()
endif ()
Loading