From deb1158532b5600315704a01e0dba540b34673da Mon Sep 17 00:00:00 2001 From: Cristian Dragoiu Date: Fri, 24 Apr 2026 20:55:33 -0400 Subject: [PATCH] Respect CMake output directory overrides --- googletest/CMakeLists.txt | 8 ++ googletest/cmake/internal_utils.cmake | 26 +++-- ...ogletest-cmake-output-directory-test.cmake | 102 ++++++++++++++++++ 3 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 googletest/test/googletest-cmake-output-directory-test.cmake diff --git a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt index 2e5388945..dd4e0e96a 100644 --- a/googletest/CMakeLists.txt +++ b/googletest/CMakeLists.txt @@ -191,6 +191,14 @@ if (gtest_build_tests) # 'make test' or ctest. enable_testing() + add_test( + NAME googletest-cmake-output-directory-test + COMMAND ${CMAKE_COMMAND} + "-DGOOGLETEST_SOURCE_DIR=${gtest_SOURCE_DIR}" + "-DGOOGLETEST_BINARY_DIR=${gtest_BINARY_DIR}/cmake_output_directory_test" + "-DGOOGLETEST_VERSION=${GOOGLETEST_VERSION}" + -P "${gtest_SOURCE_DIR}/test/googletest-cmake-output-directory-test.cmake") + ############################################################ # C++ tests built with standard compiler flags. diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake index ca76f42d7..377e05b12 100644 --- a/googletest/cmake/internal_utils.cmake +++ b/googletest/cmake/internal_utils.cmake @@ -162,19 +162,29 @@ endmacro() function(cxx_library_with_type name type cxx_flags) # type can be either STATIC or SHARED to denote a static or shared library. # ARGN refers to additional arguments after 'cxx_flags'. + # Preserve the historical default artifact layout while allowing users to + # override it with CMAKE__OUTPUT_DIRECTORY variables. + if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") + endif() + if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + endif() + if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + endif() + if(NOT DEFINED CMAKE_PDB_OUTPUT_DIRECTORY) + set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") + endif() + if(NOT DEFINED CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY) + set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + endif() + add_library(${name} ${type} ${ARGN}) add_library(${cmake_package_name}::${name} ALIAS ${name}) set_target_properties(${name} PROPERTIES COMPILE_FLAGS "${cxx_flags}") - # Set the output directory for build artifacts. - set_target_properties(${name} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" - PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" - COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") # Make PDBs match library name. get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX) set_target_properties(${name} diff --git a/googletest/test/googletest-cmake-output-directory-test.cmake b/googletest/test/googletest-cmake-output-directory-test.cmake new file mode 100644 index 000000000..bdd93a746 --- /dev/null +++ b/googletest/test/googletest-cmake-output-directory-test.cmake @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.16) + +if(NOT DEFINED GOOGLETEST_SOURCE_DIR) + message(FATAL_ERROR "GOOGLETEST_SOURCE_DIR must be set") +endif() + +if(NOT DEFINED GOOGLETEST_BINARY_DIR) + message(FATAL_ERROR "GOOGLETEST_BINARY_DIR must be set") +endif() + +function(write_output_directory_test_project source_dir) + file(MAKE_DIRECTORY "${source_dir}") + file(WRITE "${source_dir}/CMakeLists.txt" [=[ +cmake_minimum_required(VERSION 3.16) +project(googletest_output_directory_test LANGUAGES CXX C) + +set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) +set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + +add_subdirectory("${GOOGLETEST_SOURCE_DIR}" googletest) + +function(expect_target_property target property expected) + get_target_property(actual "${target}" "${property}") + if(NOT actual STREQUAL expected) + message(FATAL_ERROR + "${target} ${property}: expected '${expected}', got '${actual}'") + endif() +endfunction() + +function(expect_output_directories target) + expect_target_property( + "${target}" RUNTIME_OUTPUT_DIRECTORY + "${EXPECTED_RUNTIME_OUTPUT_DIRECTORY}") + expect_target_property( + "${target}" LIBRARY_OUTPUT_DIRECTORY + "${EXPECTED_LIBRARY_OUTPUT_DIRECTORY}") + expect_target_property( + "${target}" ARCHIVE_OUTPUT_DIRECTORY + "${EXPECTED_ARCHIVE_OUTPUT_DIRECTORY}") + expect_target_property( + "${target}" PDB_OUTPUT_DIRECTORY + "${EXPECTED_PDB_OUTPUT_DIRECTORY}") + expect_target_property( + "${target}" COMPILE_PDB_OUTPUT_DIRECTORY + "${EXPECTED_COMPILE_PDB_OUTPUT_DIRECTORY}") +endfunction() + +expect_output_directories(gtest) +expect_output_directories(gtest_main) +]=]) +endfunction() + +function(run_cmake_output_directory_test name) + set(source_dir "${GOOGLETEST_BINARY_DIR}/${name}/src") + set(binary_dir "${GOOGLETEST_BINARY_DIR}/${name}/build") + file(REMOVE_RECURSE "${source_dir}" "${binary_dir}") + write_output_directory_test_project("${source_dir}") + + set(cmake_args + -S "${source_dir}" + -B "${binary_dir}" + "-DGOOGLETEST_SOURCE_DIR=${GOOGLETEST_SOURCE_DIR}") + + if(DEFINED GOOGLETEST_VERSION) + list(APPEND cmake_args "-DGOOGLETEST_VERSION=${GOOGLETEST_VERSION}") + endif() + + foreach(arg IN LISTS ARGN) + list(APPEND cmake_args "${arg}") + endforeach() + + execute_process( + COMMAND "${CMAKE_COMMAND}" ${cmake_args} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error) + if(result) + message(FATAL_ERROR + "Configuring ${name} failed:\n${output}\n${error}") + endif() +endfunction() + +set(default_binary_dir "${GOOGLETEST_BINARY_DIR}/default/build") +run_cmake_output_directory_test(default + "-DEXPECTED_RUNTIME_OUTPUT_DIRECTORY=${default_binary_dir}/bin" + "-DEXPECTED_LIBRARY_OUTPUT_DIRECTORY=${default_binary_dir}/lib" + "-DEXPECTED_ARCHIVE_OUTPUT_DIRECTORY=${default_binary_dir}/lib" + "-DEXPECTED_PDB_OUTPUT_DIRECTORY=${default_binary_dir}/bin" + "-DEXPECTED_COMPILE_PDB_OUTPUT_DIRECTORY=${default_binary_dir}/lib") + +set(custom_binary_dir "${GOOGLETEST_BINARY_DIR}/custom/build") +run_cmake_output_directory_test(custom + "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/bin" + "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/lib" + "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/archive" + "-DCMAKE_PDB_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/pdb" + "-DCMAKE_COMPILE_PDB_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/compile-pdb" + "-DEXPECTED_RUNTIME_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/bin" + "-DEXPECTED_LIBRARY_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/lib" + "-DEXPECTED_ARCHIVE_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/archive" + "-DEXPECTED_PDB_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/pdb" + "-DEXPECTED_COMPILE_PDB_OUTPUT_DIRECTORY=${custom_binary_dir}/custom/compile-pdb")