From 4485a1e84dfc66f1a9810751cecaf138ddfc403d Mon Sep 17 00:00:00 2001 From: Fred Hornsey Date: Wed, 1 May 2024 19:31:21 -0500 Subject: [PATCH] Brute Force Check of ACE Required C++ Std in CMake Since https://github.com/OpenDDS/OpenDDS/pull/4487, CMake requires knowledge of the minimum C++ standard of ACE. Before it used the ACE version to assume it, but the required standard changed in ACE to C++17. To support this correctly in CMake, we could do a version check, but master has currently the same version as the last ACE7 release. This changes it to try to compile against `ace/Global_Macros.h` like how we currently check the compiler default. This will allow us to get any standard ACE requires as long it's a standard we're aware of. We will not need this after https://github.com/OpenDDS/OpenDDS/issues/4578, because CMake can directly tell us what ACE/TAO requires. This change still doesn't cover a case like ACE/TAO 7.1.4, where ACE/TAO was compiled with something other the compiler default or the minimum standard of ACE. CMake can't detect that, so that requires manually setting the standard in either CMake and/or the ACE/TAO build so they match. --- cmake/ace_cppstd.cpp | 2 + cmake/init.cmake | 84 ++++++++++++++++++++------- dds/DdsDcps.mpc | 1 + docs/news.d/cmake-ace-tao-cpp-std.rst | 5 ++ 4 files changed, 71 insertions(+), 21 deletions(-) create mode 100644 cmake/ace_cppstd.cpp create mode 100644 docs/news.d/cmake-ace-tao-cpp-std.rst diff --git a/cmake/ace_cppstd.cpp b/cmake/ace_cppstd.cpp new file mode 100644 index 00000000000..7a1999ea964 --- /dev/null +++ b/cmake/ace_cppstd.cpp @@ -0,0 +1,2 @@ +#include +int main() {} diff --git a/cmake/init.cmake b/cmake/init.cmake index 590399a76f6..832bf462251 100644 --- a/cmake/init.cmake +++ b/cmake/init.cmake @@ -155,6 +155,11 @@ function(_opendds_cxx_std_to_year out_var cxx_std) set(${out_var} ${year} PARENT_SCOPE) endfunction() +function(_opendds_cplusplus_to_year out_var cplusplus) + math(EXPR year "${cplusplus} / 100") + set(${out_var} ${year} PARENT_SCOPE) +endfunction() + function(_opendds_cxx_std_from_year out_var year) if(year STREQUAL 1998) set(std 98) @@ -167,14 +172,15 @@ endfunction() function(_opendds_set_cxx_std) # Get the latest known default compiler C++ standard set(default_cxx_std_year 1998) - foreach(cplusplus 201103 201402 201703 202002 202302) - try_compile(at_least + set(cplusplus_values 201103 201402 201703 202002 202302) + foreach(cplusplus IN LISTS cplusplus_values) + try_compile(compiled "${CMAKE_CURRENT_BINARY_DIR}/opendds_test_cplusplus_${cplusplus}" SOURCES "${CMAKE_CURRENT_LIST_DIR}/cplusplus.cpp" COMPILE_DEFINITIONS "-DOPENDDS_TEST_CPLUSPLUS=${cplusplus}L" ) - if(at_least) - math(EXPR default_cxx_std_year "${cplusplus} / 100") + if(compiled) + _opendds_cplusplus_to_year(default_cxx_std_year ${cplusplus}) else() break() endif() @@ -207,10 +213,8 @@ function(_opendds_set_cxx_std) endif() # Get the C++ standard ACE requires - set(ace7 FALSE) - if(NOT OPENDDS_ACE_VERSION VERSION_LESS "7.0.0") - set(ace7 TRUE) - endif() + set(ace_info "ACE ${OPENDDS_ACE_VERSION}") + set(compiler_info "compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") set(existing_cxx11 FALSE) if(OPENDDS_CXX11 OR (DEFINED _opendds_default_features_no_cxx11 AND _opendds_default_features_no_cxx11 STREQUAL "0")) @@ -220,12 +224,55 @@ function(_opendds_set_cxx_std) if(ACE_IS_BEING_BUILT AND NOT cxx_std_year LESS 2011) set(can_build_cxx11 TRUE) endif() - if(ace7) - set(ace_min_cxx_std_year 2014) - elseif(existing_cxx11 OR can_build_cxx11) - set(ace_min_cxx_std_year 2011) + if(OPENDDS_ACE_VERSION VERSION_LESS "7.0.0") + # What ACE 6 requires depends on the no_cxx11 feature + set(ace_info "${ace_info} (cxx11=${existing_cxx11})") + if(existing_cxx11 OR can_build_cxx11) + set(ace_min_cxx_std_year 2011) + else() + set(ace_min_cxx_std_year 1998) + endif() else() - set(ace_min_cxx_std_year 1998) + # What ACE 7+ requires depends on a check in ace/Global_Macros.h. We must + # compile against that header using each standard we know of until it + # compiles. + set(dir "${CMAKE_CURRENT_BINARY_DIR}/opendds_test_ace_cppstd") + set(includes "${ACE_INCLUDE_DIRS}") + if(NOT EXISTS "${ACE_INCLUDE_DIRS}/ace/config.h") + if(NOT ACE_IS_BEING_BUILT) + message(FATAL_ERROR "ACE doesn't have a config.h.") + endif() + # Won't compile without a config.h, so make a fake one. + set(include_dir "${dir}/include") + list(APPEND includes "${include_dir}") + set(ace_dir "${include_dir}/ace") + file(MAKE_DIRECTORY "${ace_dir}") + file(WRITE "${ace_dir}/config.h" "#include \n") + endif() + foreach(try_cplusplus IN LISTS cplusplus_values) + _opendds_cplusplus_to_year(try_year ${try_cplusplus}) + _opendds_cxx_std_from_year(try_std ${try_year}) + message("CMAKE_CXX_STANDARD=${try_std}") + try_compile(compiled + "${dir}/${try_cplusplus}" + SOURCES "${CMAKE_CURRENT_LIST_DIR}/ace_cppstd.cpp" + CMAKE_FLAGS + "-DCMAKE_CXX_STANDARD=${try_std}" + "-DINCLUDE_DIRECTORIES=${includes}" + OUTPUT_VARIABLE build_output + ) + if(compiled) + set(ace_min_cxx_std_year ${try_year}) + break() + endif() + endforeach() + if(NOT DEFINED ace_min_cxx_std_year) + message(FATAL_ERROR + " Can't figure out required C++ standard for ${ace_info}\n" + " Tried up to C++ ${try_year} on ${compiler_info}, last output:\n" + " \n" + " ${build_output}") + endif() endif() if(OPENDDS_CMAKE_VERBOSE) @@ -239,17 +286,12 @@ function(_opendds_set_cxx_std) # See if ACE requires a later standard if(cxx_std_year LESS ace_min_cxx_std_year) - set(compiler_info "compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") - set(ace_info "ACE ${OPENDDS_ACE_VERSION}") - if(NOT ace7) - set(ace_info "${ace_info} (cxx11=${existing_cxx11})") - endif() - set(ace_info "${ace_info} requires at least C++ ${ace_min_cxx_std_year}") + set(msg "${ace_info} requires at least C++ ${ace_min_cxx_std_year}") if(NOT explicit AND max_cxx_std_year LESS ace_min_cxx_std_year) - message(FATAL_ERROR "${ace_info}, but ${compiler_info} only supports up to " + message(FATAL_ERROR "${msg}, but ${compiler_info} only supports up to " "C++ ${max_cxx_std_year}.") endif() - message(STATUS "${compiler_info} would use ${cxx_std_year}, but ${ace_info}. Raising " + message(STATUS "${compiler_info} would use ${cxx_std_year}, but ${msg}. Raising " "requirment to that.") set(cxx_std_year ${ace_min_cxx_std_year}) endif() diff --git a/dds/DdsDcps.mpc b/dds/DdsDcps.mpc index fda2efbad65..00d2fbe853f 100644 --- a/dds/DdsDcps.mpc +++ b/dds/DdsDcps.mpc @@ -113,6 +113,7 @@ project(OpenDDS_Dcps): core, coverage_optional, \ " @$(MKDIR) $(cmake_dir_install_dest)" " cp $(DDS_ROOT)/cmake/*.cmake $(cmake_dir_install_dest)" " cp $(DDS_ROOT)/cmake/cplusplus.cpp $(cmake_dir_install_dest)" +" cp $(DDS_ROOT)/cmake/ace_cppstd.cpp $(cmake_dir_install_dest)" " cp $(DDS_ROOT)/cmake/export.h.in $(cmake_dir_install_dest)" " echo '' >> $(cmake_config_install_dest)" " echo '# From make install' >> $(cmake_config_install_dest)" diff --git a/docs/news.d/cmake-ace-tao-cpp-std.rst b/docs/news.d/cmake-ace-tao-cpp-std.rst new file mode 100644 index 00000000000..8f52ea8444f --- /dev/null +++ b/docs/news.d/cmake-ace-tao-cpp-std.rst @@ -0,0 +1,5 @@ +.. news-prs: 4618 + +.. news-start-section: Platform Support and Dependencies +- Fix cases where the CMake support fails when using the ACE/TAO master branch because it now requires C++17. +.. news-end-section. news-end-section