diff --git a/cmake/ace_cppstd.cpp b/cmake/ace_cppstd.cpp new file mode 100644 index 00000000000..1375ba8ee98 --- /dev/null +++ b/cmake/ace_cppstd.cpp @@ -0,0 +1,7 @@ +#define ACE_DOESNT_DEFINE_MAIN 1 +#include + +int main() +{ + return 0; +} diff --git a/cmake/init.cmake b/cmake/init.cmake index 590399a76f6..06cc1badb8a 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,54 @@ 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}) + 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 +285,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