From c3236a29fca53ffa8f1bb4d85033fb0b5b218766 Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Sat, 24 Aug 2024 21:23:35 +0200 Subject: [PATCH] build: Refactor build_lib and static/monolib target setups --- build-support/cmake-format.yaml | 8 + ...-fetch-optional-modules-dependencies.cmake | 5 - .../custom-modules/ns3-module-macros.cmake | 556 ++++++++++-------- build-support/macros-and-definitions.cmake | 8 - src/CMakeLists.txt | 169 ++++-- src/core/CMakeLists.txt | 13 + utils/tests/test-ns3.py | 45 +- 7 files changed, 454 insertions(+), 350 deletions(-) diff --git a/build-support/cmake-format.yaml b/build-support/cmake-format.yaml index 1d2ce71e4..afc2664d2 100644 --- a/build-support/cmake-format.yaml +++ b/build-support/cmake-format.yaml @@ -56,6 +56,14 @@ additional_commands: CMAKE_PACKAGES : '*' EXECUTABLES : '*' PYTHON_PACKAGES : '*' + copy_headers: + kwargs: + PUBLIC_HEADER_OUTPUT_DIR: '1' + DEPRECATED_HEADER_OUTPUT_DIR: '1' + PRIVATE_HEADER_OUTPUT_DIR: '1' + PUBLIC_HEADER_FILES: '*' + DEPRECATED_HEADER_FILES: '*' + PRIVATE_HEADER_FILES: '*' format: tab_size: 2 diff --git a/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake b/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake index 583430995..07d628334 100644 --- a/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake +++ b/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake @@ -85,9 +85,4 @@ macro(add_dependency_to_optional_modules_dependencies) add_dependencies(${libbrite} brite_dep) add_dependencies(${libclick} click_dep) add_dependencies(${libopenflow} openflow_dep) - if(NOT ${XCODE}) - add_dependencies(${libbrite}-obj brite_dep) - add_dependencies(${libclick}-obj click_dep) - add_dependencies(${libopenflow}-obj openflow_dep) - endif() endmacro() diff --git a/build-support/custom-modules/ns3-module-macros.cmake b/build-support/custom-modules/ns3-module-macros.cmake index f4cf3c98d..9d3597852 100644 --- a/build-support/custom-modules/ns3-module-macros.cmake +++ b/build-support/custom-modules/ns3-module-macros.cmake @@ -47,6 +47,40 @@ function(copy_headers_before_building_lib libname outputdir headers visibility) endforeach() endfunction(copy_headers_before_building_lib) +function(copy_headers) + # Argument parsing + set(options) + set(oneValueArgs PUBLIC_HEADER_OUTPUT_DIR DEPRECATED_HEADER_OUTPUT_DIR + PRIVATE_HEADER_OUTPUT_DIR + ) + set(multiValueArgs PUBLIC_HEADER_FILES DEPRECATED_HEADER_FILES + PRIVATE_HEADER_FILES + ) + cmake_parse_arguments( + "CP" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} + ) + if((DEFINED CP_PUBLIC_HEADER_OUTPUT_DIR) AND (DEFINED CP_PUBLIC_HEADER_FILES)) + copy_headers_before_building_lib( + "" "${CP_PUBLIC_HEADER_OUTPUT_DIR}" "${CP_PUBLIC_HEADER_FILES}" public + ) + endif() + if((DEFINED CP_DEPRECATED_HEADER_OUTPUT_DIR) AND (DEFINED + CP_DEPRECATED_HEADER_FILES) + ) + copy_headers_before_building_lib( + "" "${CP_DEPRECATED_HEADER_OUTPUT_DIR}" "${CP_DEPRECATED_HEADER_FILES}" + deprecated + ) + endif() + if((DEFINED CP_PRIVATE_HEADER_OUTPUT_DIR) AND (DEFINED CP_PRIVATE_HEADER_FILES + ) + ) + copy_headers_before_building_lib( + "" "${CP_PRIVATE_HEADER_OUTPUT_DIR}" "${CP_PRIVATE_HEADER_FILES}" private + ) + endif() +endfunction() + function(remove_lib_prefix prefixed_library library) # Check if there is a lib prefix string(FIND "${prefixed_library}" "lib" lib_pos) @@ -138,60 +172,27 @@ function(build_lib) ) endif() - if(NOT ${XCODE}) - # Create object library with sources and headers, that will be used in - # lib-ns3-static and the shared library - add_library( - ${BLIB_LIBNAME}-obj OBJECT "${BLIB_SOURCE_FILES}" "${BLIB_HEADER_FILES}" - ) - - if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH})) - target_precompile_headers(${BLIB_LIBNAME}-obj REUSE_FROM stdlib_pch) - endif() - - # Create shared library with previously created object library (saving - # compilation time for static libraries) - add_library(${BLIB_LIBNAME} SHARED $) - else() - # Xcode and CMake don't play well when using object libraries, so we have a - # specific path for that - add_library(${BLIB_LIBNAME} SHARED "${BLIB_SOURCE_FILES}") - - if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH})) - target_precompile_headers(${BLIB_LIBNAME} REUSE_FROM stdlib_pch) - endif() - endif() + # Create the module shared library + add_library(${BLIB_LIBNAME} SHARED "${BLIB_SOURCE_FILES}") + # Set alias add_library(ns3::${BLIB_LIBNAME} ALIAS ${BLIB_LIBNAME}) - # Associate public headers with library for installation purposes - set(config_headers) - if("${BLIB_LIBNAME}" STREQUAL "core") - set(config_headers ${CMAKE_HEADER_OUTPUT_DIRECTORY}/config-store-config.h - ${CMAKE_HEADER_OUTPUT_DIRECTORY}/core-config.h - ) - if(${ENABLE_BUILD_VERSION}) - list(APPEND config_headers - ${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h - ) - endif() - - # Enable examples as tests suites - if(${ENABLE_EXAMPLES} AND ${ENABLE_TESTS}) - if(NOT ${XCODE}) - target_compile_definitions( - ${BLIB_LIBNAME}-obj PRIVATE NS3_ENABLE_EXAMPLES - ) - else() - target_compile_definitions(${BLIB_LIBNAME} PRIVATE NS3_ENABLE_EXAMPLES) - endif() - endif() + # Reuse PCH + if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH})) + target_precompile_headers(${BLIB_LIBNAME} REUSE_FROM stdlib_pch) endif() + + if(${ENABLE_EXAMPLES} AND ${ENABLE_TESTS}) + target_compile_definitions(${BLIB_LIBNAME} PRIVATE NS3_ENABLE_EXAMPLES) + endif() + + # Associate public headers with library for installation purposes set_target_properties( ${BLIB_LIBNAME} PROPERTIES PUBLIC_HEADER - "${BLIB_HEADER_FILES};${BLIB_DEPRECATED_HEADER_FILES};${config_headers};${CMAKE_HEADER_OUTPUT_DIRECTORY}/${BLIB_LIBNAME}-module.h" + "${BLIB_HEADER_FILES};${BLIB_DEPRECATED_HEADER_FILES};${CMAKE_HEADER_OUTPUT_DIRECTORY}/${BLIB_LIBNAME}-module.h" PRIVATE_HEADER "${BLIB_PRIVATE_HEADER_FILES}" RUNTIME_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} # set output # directory for @@ -202,35 +203,72 @@ function(build_lib) add_dependencies(timeTraceReport ${BLIB_LIBNAME}) endif() - # Split ns and non-ns libraries to manage their propagation properly - set(non_ns_libraries_to_link ${CMAKE_THREAD_LIBS_INIT}) + build_lib_reexport_third_party_libraries( + "${BLIB_LIBNAME}" "${BLIB_LIBRARIES_TO_LINK}" + ) - set(ns_libraries_to_link) + # set output name of library + set_target_properties( + ${BLIB_LIBNAME} + PROPERTIES OUTPUT_NAME ns${NS3_VER}-${BLIB_LIBNAME}${build_profile_suffix} + ) - foreach(library ${BLIB_LIBRARIES_TO_LINK}) - remove_lib_prefix("${library}" module_name) + # Export compile definitions as interface definitions, propagating local + # definitions to other modules and scratches + build_lib_export_definitions_as_interface_definitions(${BLIB_LIBNAME}) - # In case the dependency library matches the ns-3 module, we are most likely - # dealing with brite, click and openflow collisions. All the ns-3 module - # targets used to be prefixed with 'lib' to be differentiable, but now we - # are dropping it. To disambiguate them two, we assume these external - # libraries are shared libraries by adding suffixes. - if("${library}" STREQUAL "${BLIB_LIBNAME}") - list(APPEND non_ns_libraries_to_link - ${library}${CMAKE_SHARED_LIBRARY_SUFFIX} - ) - continue() - endif() + # Write a module header that includes all headers from that module + write_module_header("${BLIB_LIBNAME}" "${BLIB_HEADER_FILES}") - # Check if the module exists in the ns-3 modules list or if it is a - # 3rd-party library - if(${module_name} IN_LIST ns3-all-enabled-modules) - list(APPEND ns_libraries_to_link ${library}) - else() - list(APPEND non_ns_libraries_to_link ${library}) - endif() - unset(module_name) - endforeach() + # Check if headers actually exist to prevent copying errors during + # installation (includes the module header created above) + build_lib_check_headers(${BLIB_LIBNAME}) + + # Copy all header files to outputfolder/include before each build + copy_headers( + PUBLIC_HEADER_OUTPUT_DIR ${CMAKE_HEADER_OUTPUT_DIRECTORY} + PUBLIC_HEADER_FILES ${BLIB_HEADER_FILES} + DEPRECATED_HEADER_OUTPUT_DIR ${CMAKE_HEADER_OUTPUT_DIRECTORY} + DEPRECATED_HEADER_FILES ${BLIB_DEPRECATED_HEADER_FILES} + PRIVATE_HEADER_OUTPUT_DIR ${CMAKE_HEADER_OUTPUT_DIRECTORY} + PRIVATE_HEADER_FILES ${BLIB_PRIVATE_HEADER_FILES} + ) + + # Scan for C++ and Python examples and return a list of C++ examples (which + # can be set as dependencies of examples-as-test test suites) + build_lib_scan_examples(module_examples) + + # Build tests if requested + build_lib_tests( + "${BLIB_LIBNAME}" "${BLIB_IGNORE_PCH}" "${FOLDER}" "${BLIB_TEST_SOURCES}" + ) + + # Handle package export + install( + TARGETS ${BLIB_LIBNAME} + EXPORT ns3ExportTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/ + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/ + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ns3" + PRIVATE_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ns3" + ) + if(${NS3_VERBOSE}) + message(STATUS "Processed ${FOLDER}") + endif() +endfunction() + +function(build_lib_reexport_third_party_libraries libname libraries_to_link) + # Separate ns-3 and non-ns-3 libraries to manage their propagation properly + separate_ns3_from_non_ns3_libs( + "${libname}" "${libraries_to_link}" ns_libraries_to_link + non_ns_libraries_to_link + ) + + set(ns3-external-libs "${non_ns_libraries_to_link};${ns3-external-libs}" + CACHE INTERNAL + "list of non-ns libraries to link to NS3_STATIC and NS3_MONOLIB" + ) if(NOT ${NS3_REEXPORT_THIRD_PARTY_LIBRARIES}) # ns-3 libraries are linked publicly, to make sure other modules can find @@ -257,7 +295,7 @@ function(build_lib) # with NS3_REEXPORT_THIRD_PARTY_LIBRARIES, we export all 3rd-party library # include directories, allowing consumers of this module to include and link # the 3rd-party code with no additional setup - get_target_includes(${BLIB_LIBNAME} exported_include_directories) + get_target_includes(${libname} exported_include_directories) string(REPLACE "-I" "" exported_include_directories "${exported_include_directories}" @@ -286,34 +324,22 @@ function(build_lib) "${exported_include_directories}" ) endif() - - target_link_libraries( - ${BLIB_LIBNAME} ${exported_libraries} ${private_libraries} - ) - - if(NOT ${XCODE}) - target_link_libraries(${BLIB_LIBNAME}-obj PRIVATE ${ns_libraries_to_link}) - endif() - - # set output name of library - set_target_properties( - ${BLIB_LIBNAME} - PROPERTIES OUTPUT_NAME ns${NS3_VER}-${BLIB_LIBNAME}${build_profile_suffix} - ) + # Set public and private headers linked to the module library + target_link_libraries(${libname} ${exported_libraries} ${private_libraries}) # export include directories used by this library so that it can be used by # 3rd-party consumers of ns-3 using find_package(ns3) this will automatically # add the build/include path to them, so that they can ns-3 headers with # target_include_directories( - ${BLIB_LIBNAME} PUBLIC $ - $ + ${libname} PUBLIC $ + $ INTERFACE ${exported_include_directories} ) +endfunction() - # Export definitions as interface definitions, propagating local definitions - # to other modules and scratches - get_target_property(target_definitions ${BLIB_LIBNAME} COMPILE_DEFINITIONS) +function(build_lib_export_definitions_as_interface_definitions libname) + get_target_property(target_definitions ${libname} COMPILE_DEFINITIONS) if(${target_definitions} STREQUAL "target_definitions-NOTFOUND") set(target_definitions) endif() @@ -322,167 +348,9 @@ function(build_lib) list(REMOVE_DUPLICATES exported_definitions) list(REMOVE_ITEM exported_definitions "") set_target_properties( - ${BLIB_LIBNAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS - "${exported_definitions}" + ${libname} PROPERTIES INTERFACE_COMPILE_DEFINITIONS + "${exported_definitions}" ) - - set(ns3-external-libs "${non_ns_libraries_to_link};${ns3-external-libs}" - CACHE INTERNAL - "list of non-ns libraries to link to NS3_STATIC and NS3_MONOLIB" - ) - if(${NS3_STATIC} OR ${NS3_MONOLIB}) - set(lib-ns3-static-objs - "$;${lib-ns3-static-objs}" - CACHE - INTERNAL - "list of object files from module used by NS3_STATIC and NS3_MONOLIB" - ) - endif() - - # Write a module header that includes all headers from that module - write_module_header("${BLIB_LIBNAME}" "${BLIB_HEADER_FILES}") - - # Check if headers actually exist to prevent copying errors during - # installation - get_target_property(headers_to_check ${BLIB_LIBNAME} PUBLIC_HEADER) - set(missing_headers) - foreach(header ${headers_to_check}) - if(NOT ((EXISTS ${header}) OR (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${header}) - ) - ) - list(APPEND missing_headers ${header}) - endif() - endforeach() - if(missing_headers) - message( - FATAL_ERROR "Missing header files for ${BLIB_LIBNAME}: ${missing_headers}" - ) - endif() - - # Copy all header files to outputfolder/include before each build - copy_headers_before_building_lib( - ${BLIB_LIBNAME} ${CMAKE_HEADER_OUTPUT_DIRECTORY} "${BLIB_HEADER_FILES}" - public - ) - if(BLIB_PRIVATE_HEADER_FILES) - copy_headers_before_building_lib( - ${BLIB_LIBNAME} ${CMAKE_HEADER_OUTPUT_DIRECTORY} - "${BLIB_PRIVATE_HEADER_FILES}" private - ) - endif() - - if(BLIB_DEPRECATED_HEADER_FILES) - copy_headers_before_building_lib( - ${BLIB_LIBNAME} ${CMAKE_HEADER_OUTPUT_DIRECTORY} - "${BLIB_DEPRECATED_HEADER_FILES}" deprecated - ) - endif() - - # Build lib examples if requested - set(examples_before ${ns3-execs-clean}) - foreach(example_folder example;examples) - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}) - if(${ENABLE_EXAMPLES}) - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}/CMakeLists.txt) - add_subdirectory(${example_folder}) - endif() - endif() - scan_python_examples(${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}) - endif() - endforeach() - set(module_examples ${ns3-execs-clean}) - - # Filter only module examples - foreach(example ${examples_before}) - list(REMOVE_ITEM module_examples ${example}) - endforeach() - unset(examples_before) - - # Check if the module tests should be built - set(filtered_in ON) - if(NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) - set(filtered_in OFF) - if(${BLIB_LIBNAME} IN_LIST NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) - set(filtered_in ON) - endif() - endif() - - # Build tests if requested - if(${ENABLE_TESTS} AND ${filtered_in}) - list(LENGTH BLIB_TEST_SOURCES test_source_len) - if(${test_source_len} GREATER 0) - # Create BLIB_LIBNAME of output library test of module - set(test${BLIB_LIBNAME} ${BLIB_LIBNAME}-test CACHE INTERNAL "") - - # Create shared library containing tests of the module on UNIX and just - # the object file that will be part of test-runner on Windows - if(WIN32) - set(ns3-libs-tests - "$;${ns3-libs-tests}" - CACHE INTERNAL "list of test libraries" - ) - add_library(${test${BLIB_LIBNAME}} OBJECT "${BLIB_TEST_SOURCES}") - else() - set(ns3-libs-tests "${test${BLIB_LIBNAME}};${ns3-libs-tests}" - CACHE INTERNAL "list of test libraries" - ) - add_library(${test${BLIB_LIBNAME}} SHARED "${BLIB_TEST_SOURCES}") - - # Link test library to the module library - if(${NS3_MONOLIB}) - target_link_libraries( - ${test${BLIB_LIBNAME}} ${LIB_AS_NEEDED_PRE} ${lib-ns3-monolib} - ${LIB_AS_NEEDED_POST} - ) - else() - target_link_libraries( - ${test${BLIB_LIBNAME}} ${LIB_AS_NEEDED_PRE} ${BLIB_LIBNAME} - "${BLIB_LIBRARIES_TO_LINK}" ${LIB_AS_NEEDED_POST} - ) - endif() - set_target_properties( - ${test${BLIB_LIBNAME}} - PROPERTIES OUTPUT_NAME - ns${NS3_VER}-${BLIB_LIBNAME}-test${build_profile_suffix} - ) - endif() - target_compile_definitions( - ${test${BLIB_LIBNAME}} PRIVATE NS_TEST_SOURCEDIR="${FOLDER}/test" - ) - if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH})) - target_precompile_headers(${test${BLIB_LIBNAME}} REUSE_FROM stdlib_pch) - endif() - - # Add dependency between tests and examples used as tests - if(${ENABLE_EXAMPLES}) - foreach(source_file ${BLIB_TEST_SOURCES}) - file(READ ${source_file} source_file_contents) - foreach(example_as_test ${module_examples}) - string(FIND "${source_file_contents}" "${example_as_test}" - is_sub_string - ) - if(NOT (${is_sub_string} EQUAL -1)) - add_dependencies(test-runner-examples-as-tests ${example_as_test}) - endif() - endforeach() - endforeach() - endif() - endif() - endif() - - # Handle package export - install( - TARGETS ${BLIB_LIBNAME} - EXPORT ns3ExportTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/ - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/ - RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/ - PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ns3" - PRIVATE_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ns3" - ) - if(${NS3_VERBOSE}) - message(STATUS "Processed ${FOLDER}") - endif() endfunction() # cmake-format: off @@ -512,13 +380,7 @@ function(build_lib_example) ) # Check if a module example should be built - set(filtered_in ON) - if(NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) - set(filtered_in OFF) - if(${BLIB_LIBNAME} IN_LIST NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) - set(filtered_in ON) - endif() - endif() + build_lib_check_examples_and_tests_filtered_in(${BLIB_LIBNAME} filtered_in) if((NOT missing_dependencies) AND ${filtered_in}) # Convert boolean into text to forward argument @@ -542,6 +404,184 @@ function(build_lib_example) endif() endfunction() +# Check if module examples and tests should be built or not +# +# Arguments: libname (e.g. core, wifi), filtered_in (return boolean) +function(build_lib_check_examples_and_tests_filtered_in libname filtered_in) + set(in ON) + if(NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) + set(in OFF) + if(${libname} IN_LIST NS3_FILTER_MODULE_EXAMPLES_AND_TESTS) + set(in ON) + endif() + endif() + set(${filtered_in} ${in} PARENT_SCOPE) +endfunction() + +# Separate the LIBRARIES_TO_LINK list into ns-3 modules and external libraries +# +# Arguments: libname (e.g. core, wifi), libraries_to_link (input list), +# ns_libraries_to_link and non_ns_libraries_to_link (output lists) +function(separate_ns3_from_non_ns3_libs libname libraries_to_link + ns_libraries_to_link non_ns_libraries_to_link +) + set(non_ns_libs ${CMAKE_THREAD_LIBS_INIT}) + set(ns_libs) + foreach(library ${libraries_to_link}) + remove_lib_prefix("${library}" module_name) + + # In case the dependency library matches the ns-3 module, we are most likely + # dealing with brite, click and openflow collisions. All the ns-3 module + # targets used to be prefixed with 'lib' to be differentiable, but now we + # are dropping it. To disambiguate them two, we assume these external + # libraries are shared libraries by adding suffixes. + if("${library}" STREQUAL "${libname}") + list(APPEND non_ns_libs ${library}${CMAKE_SHARED_LIBRARY_SUFFIX}) + continue() + endif() + + # Check if the module exists in the ns-3 modules list or if it is a + # 3rd-party library + if(${module_name} IN_LIST ns3-all-enabled-modules) + list(APPEND ns_libs ${library}) + else() + list(APPEND non_ns_libs ${library}) + endif() + unset(module_name) + endforeach() + set(${ns_libraries_to_link} ${ns_libs} PARENT_SCOPE) + set(${non_ns_libraries_to_link} ${non_ns_libs} PARENT_SCOPE) +endfunction() + +# This macro scans for C++ and Python examples for a given module and return a +# list of C++ examples +# +# Arguments: module_cpp_examples = return list of C++ examples +function(build_lib_scan_examples module_cpp_examples) + # Build lib examples if requested + set(examples_before ${ns3-execs-clean}) + foreach(example_folder example;examples) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}) + if(${ENABLE_EXAMPLES}) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}/CMakeLists.txt) + add_subdirectory(${example_folder}) + endif() + endif() + scan_python_examples(${CMAKE_CURRENT_SOURCE_DIR}/${example_folder}) + endif() + endforeach() + set(module_examples ${ns3-execs-clean}) + + # Return a list of module c++ examples (current examples - previous examples) + list(REMOVE_ITEM module_examples ${examples_before}) + set(${module_cpp_examples} ${module_examples} PARENT_SCOPE) +endfunction() + +# This macro builds the test library for the module library +# +# Arguments: libname (e.g. core), ignore_pch (TRUE/FALSE), folder (src/contrib), +# sources (list of .cc's) +function(build_lib_tests libname ignore_pch folder test_sources) + if(${ENABLE_TESTS}) + # Check if the module tests should be built + build_lib_check_examples_and_tests_filtered_in(${libname} filtered_in) + if(NOT ${filtered_in}) + return() + endif() + list(LENGTH test_sources test_source_len) + if(${test_source_len} GREATER 0) + # Create libname of output library test of module + set(test${libname} ${libname}-test CACHE INTERNAL "") + + # Create shared library containing tests of the module on UNIX and just + # the object file that will be part of test-runner on Windows + if(WIN32) + set(ns3-libs-tests + "$;${ns3-libs-tests}" + CACHE INTERNAL "list of test libraries" + ) + add_library(${test${libname}} OBJECT "${test_sources}") + else() + set(ns3-libs-tests "${test${libname}};${ns3-libs-tests}" + CACHE INTERNAL "list of test libraries" + ) + add_library(${test${libname}} SHARED "${test_sources}") + + # Link test library to the module library + if(${NS3_MONOLIB}) + target_link_libraries( + ${test${libname}} ${LIB_AS_NEEDED_PRE} ${lib-ns3-monolib} + ${LIB_AS_NEEDED_POST} + ) + else() + target_link_libraries( + ${test${libname}} ${LIB_AS_NEEDED_PRE} ${libname} + "${BLIB_LIBRARIES_TO_LINK}" ${LIB_AS_NEEDED_POST} + ) + endif() + set_target_properties( + ${test${libname}} + PROPERTIES OUTPUT_NAME + ns${NS3_VER}-${libname}-test${build_profile_suffix} + ) + endif() + target_compile_definitions( + ${test${libname}} PRIVATE NS_TEST_SOURCEDIR="${folder}/test" + ) + if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${ignore_pch})) + target_precompile_headers(${test${libname}} REUSE_FROM stdlib_pch) + endif() + + # Add dependency between tests and examples used as tests + examples_as_tests_dependencies("${module_examples}" "${test_sources}") + endif() + endif() +endfunction() + +# This macro scans for C++ examples used by examples-as-tests suites +# +# Arguments: module_cpp_examples = list of C++ example executable names, +# module_test_sources = list of C++ sources with tests +function(examples_as_tests_dependencies module_cpp_examples module_test_sources) + if(${ENABLE_EXAMPLES}) + foreach(source_file ${module_test_sources}) + file(READ ${source_file} source_file_contents) + foreach(example_as_test ${module_cpp_examples}) + string(FIND "${source_file_contents}" "${example_as_test}" + is_sub_string + ) + if(NOT (${is_sub_string} EQUAL -1)) + add_dependencies(test-runner-examples-as-tests ${example_as_test}) + endif() + endforeach() + endforeach() + endif() +endfunction() + +# This macro checks if all headers from a module actually exist or are missing +# +# Arguments: target_name = module name (e.g. core, wifi) +function(build_lib_check_headers target_name) + # Retrieve target properties containing the public (which include deprecated) + # and private headers + get_target_property(headers_to_check ${target_name} PUBLIC_HEADER) + get_target_property(headers_to_check2 ${target_name} PRIVATE_HEADER) + list(APPEND headers_to_check ${headers_to_check2}) + set(missing_headers) + foreach(header ${headers_to_check}) + if(NOT ((EXISTS ${header}) OR (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${header}) + ) + ) + list(APPEND missing_headers ${header}) + endif() + endforeach() + if(missing_headers) + message( + FATAL_ERROR "Missing header files for ${target_name}: ${missing_headers}" + ) + endif() +endfunction() + # This macro processes a ns-3 module header file (module_name-module.h) # # Arguments: name = module name (e.g. core, wifi) HEADER_FILES = diff --git a/build-support/macros-and-definitions.cmake b/build-support/macros-and-definitions.cmake index c93ecc2a7..28bec9729 100644 --- a/build-support/macros-and-definitions.cmake +++ b/build-support/macros-and-definitions.cmake @@ -99,12 +99,6 @@ macro(clear_global_cached_variables) # clear cache variables unset(build_profile CACHE) unset(build_profile_suffix CACHE) - set(lib-ns3-static-objs - "" - CACHE - INTERNAL - "list of object files from module used by NS3_STATIC and NS3_MONOLIB" - ) set(ns3-contrib-libs "" CACHE INTERNAL "list of processed contrib modules") set(ns3-example-folders "" CACHE INTERNAL "list of example folders") set(ns3-execs "" CACHE INTERNAL "list of c++ executables") @@ -121,7 +115,6 @@ macro(clear_global_cached_variables) mark_as_advanced( build_profile build_profile_suffix - lib-ns3-static-objs ns3-contrib-libs ns3-example-folders ns3-execs @@ -1199,7 +1192,6 @@ macro(process_options) set(ns3-all-enabled-modules) set(ns3-libs-tests) set(ns3-contrib-libs) - set(lib-ns3-static-objs) set(ns3-external-libs) foreach(libname ${scanned_modules}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52f65e9f8..2be102398 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,71 +53,124 @@ foreach(libname ${modules}) endif() endforeach() -# Prevents link errors due to symbol collisions if the same library is linked -# multiple times -list(REMOVE_DUPLICATES ns3-external-libs) +if(NOT ${XCODE}) -# Build the lib-ns3-static (ns3.x-static-buildtype.a/.lib) with all sublibraries -if(${NS3_STATIC}) - add_library( - ${lib-ns3-static} STATIC ${PROJECT_SOURCE_DIR}/build-support/empty.cc - "${lib-ns3-static-objs}" - ) + # Create object libraries from shared libraries to be reused by static and + # monolib builds + set(lib-ns3-static-objs) + if(${NS3_STATIC} OR ${NS3_MONOLIB}) + foreach(module ${ns3-libs} ${ns3-contrib-libs}) + # Retrieve source files from shared library target + get_target_property(target_sources ${module} SOURCES) - # Replace shared library suffix and check if static version exists before - # linking - set(ns3-external-static-libs) - foreach(sharedlib ${ns3-external-libs}) - if(NOT (${sharedlib} MATCHES ".so")) - list(APPEND ns3-external-static-libs ${sharedlib}) - continue() - endif() - - string(REPLACE ".so" ".a" output ${sharedlib}) - if(EXISTS ${output}) - list(APPEND ns3-external-static-libs ${output}) - else() - message( - FATAL_ERROR "Static library version of ${sharedlib} was not found" + # Prepend module path to source files + set(FOLDER "src") + if(${module} IN_LIST ns3-contrib-libs) + set(FOLDER "contrib") + endif() + list(TRANSFORM target_sources + PREPEND ${PROJECT_SOURCE_DIR}/${FOLDER}/${module}/ ) + + # Create object library from shared library + add_library(${module}-obj OBJECT ${target_sources}) + + # Reuse PCH + if(${PRECOMPILE_HEADERS_ENABLED}) + target_precompile_headers(${module}-obj REUSE_FROM stdlib_pch) + endif() + + # Retrieve properties from shared library target and apply to object + foreach(property INCLUDE_DIRECTORIES LINK_DIRECTORIES + INTERFACE_COMPILE_DEFINITIONS + ) + get_target_property(target_definitions ${module} ${property}) + if("${target_definitions}" MATCHES "target_definitions-NOTFOUND") + continue() + endif() + if(${property} STREQUAL "INTERFACE_COMPILE_DEFINITIONS") + set(property COMPILE_DEFINITIONS) + endif() + + set_target_properties( + ${module}-obj PROPERTIES ${property} "${target_definitions}" + ) + endforeach() + + # Append to the list of object files + list(APPEND lib-ns3-static-objs $) + endforeach() + endif() + + # Prevents link errors due to symbol collisions if the same library is linked + # multiple times + list(REMOVE_DUPLICATES ns3-external-libs) + + # Build the lib-ns3-static (ns3.x-static-buildtype.a/.lib) with all + # sublibraries + if(${NS3_STATIC}) + add_library( + ${lib-ns3-static} STATIC ${PROJECT_SOURCE_DIR}/build-support/empty.cc + "${lib-ns3-static-objs}" + ) + + # Replace shared library suffix and check if static version exists before + # linking + set(ns3-external-static-libs) + foreach(sharedlib ${ns3-external-libs}) + if(NOT (${sharedlib} MATCHES ".so")) + list(APPEND ns3-external-static-libs ${sharedlib}) + continue() + endif() + + string(REPLACE ".so" ".a" output ${sharedlib}) + if(EXISTS ${output}) + list(APPEND ns3-external-static-libs ${output}) + else() + message( + FATAL_ERROR "Static library version of ${sharedlib} was not found" + ) + endif() + endforeach() + + # Required by some static libraries, such as sqlite, for some odd reason + if(LINUX) + list(APPEND ns3-external-static-libs -ldl) endif() - endforeach() - # Required by some static libraries, such as sqlite, for some odd reason - if(LINUX) - list(APPEND ns3-external-static-libs -ldl) - endif() + target_link_libraries( + ${lib-ns3-static} ${STATIC_LINK_FLAGS} ${LIB_AS_NEEDED_PRE_STATIC} + ${ns3-external-static-libs} ${LIB_AS_NEEDED_POST_STATIC} + ) + if(${NS3_CLANG_TIMETRACE}) + add_dependencies(timeTraceReport ${lib-ns3-static}) + endif() + endif() # NS3_STATIC - target_link_libraries( - ${lib-ns3-static} ${STATIC_LINK_FLAGS} ${LIB_AS_NEEDED_PRE_STATIC} - ${ns3-external-static-libs} ${LIB_AS_NEEDED_POST_STATIC} - ) - if(${NS3_CLANG_TIMETRACE}) - add_dependencies(timeTraceReport ${lib-ns3-static}) - endif() -endif() + # Build the lib-ns3 (ns3.x-monolib-buildtype.dll/.dylib/.so) with all + # sublibraries + if(${NS3_MONOLIB}) + add_library( + ${lib-ns3-monolib} SHARED ${PROJECT_SOURCE_DIR}/build-support/empty.cc + "${lib-ns3-static-objs}" + ) + set_target_properties( + ${lib-ns3-monolib} + PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE + RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} # set output directory for + # DLLs + ) + target_link_libraries( + ${lib-ns3-monolib} ${LIB_AS_NEEDED_PRE} ${ns3-external-libs} + ${LIB_AS_NEEDED_POST} + ) + if(${NS3_CLANG_TIMETRACE}) + add_dependencies(timeTraceReport ${lib-ns3-monolib}) + endif() + endif() # NS3_MONOLIB -# Build the lib-ns3 (ns3.x-monolib-buildtype.dll/.dylib/.so) with all -# sublibraries -if(${NS3_MONOLIB}) - add_library( - ${lib-ns3-monolib} SHARED ${PROJECT_SOURCE_DIR}/build-support/empty.cc - "${lib-ns3-static-objs}" - ) - set_target_properties( - ${lib-ns3-monolib} - PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE - RUNTIME_OUTPUT_DIRECTORY - ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} # set output directory for DLLs - ) - target_link_libraries( - ${lib-ns3-monolib} ${LIB_AS_NEEDED_PRE} ${ns3-external-libs} - ${LIB_AS_NEEDED_POST} - ) - if(${NS3_CLANG_TIMETRACE}) - add_dependencies(timeTraceReport ${lib-ns3-monolib}) - endif() -endif() +endif() # NOT XCODE if(${NS3_FETCH_OPTIONAL_COMPONENTS}) add_dependency_to_optional_modules_dependencies() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 12a4f3aec..3428f35f3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,6 +1,18 @@ # Set lib core link dependencies set(libraries_to_link) +set(config_headers + ${CMAKE_HEADER_OUTPUT_DIRECTORY}/config-store-config.h + ${CMAKE_HEADER_OUTPUT_DIRECTORY}/core-config.h +) +if(${ENABLE_BUILD_VERSION}) + list( + APPEND + config_headers + ${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h + ) +endif() + set(gsl_test_sources) if(${GSL_FOUND}) set(libraries_to_link @@ -188,6 +200,7 @@ set(source_files # Define core lib headers set(header_files + ${config_headers} ${int64x64_headers} ${example_as_test_headers} ${embedded_version_headers} diff --git a/utils/tests/test-ns3.py b/utils/tests/test-ns3.py index a27a65cfe..0db4d4f87 100755 --- a/utils/tests/test-ns3.py +++ b/utils/tests/test-ns3.py @@ -1291,7 +1291,7 @@ class NS3ConfigureTestCase(NS3BaseTestCase): ) return_code, stdout, stderr = run_ns3("run abort") if win32: - self.assertEqual(return_code, 3) + self.assertNotEqual(return_code, 0) self.assertIn("abort-default.exe' returned non-zero exit status", stdout) else: self.assertEqual(return_code, 250) @@ -2595,6 +2595,9 @@ class NS3BuildBaseTestCase(NS3BaseTestCase): if shutil.which("git") is None: self.skipTest("Missing git") + if win32: + self.skipTest("Optional components are not supported on Windows") + # First enable automatic components fetching return_code, stdout, stderr = run_ns3("configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON") self.assertEqual(return_code, 0) @@ -3158,30 +3161,30 @@ class NS3ExpectedUseTestCase(NS3BaseTestCase): return_code, stdout, stderr = run_ns3("clean") self.assertEqual(return_code, 0) - if arch != "aarch64": - # Install VcPkg dependencies - container.execute("apt-get install -y zip unzip tar curl") + if arch != "aarch64": + # Install VcPkg dependencies + container.execute("apt-get install -y zip unzip tar curl") - # Install Armadillo dependencies - container.execute("apt-get install -y pkg-config gfortran") + # Install Armadillo dependencies + container.execute("apt-get install -y pkg-config gfortran") - # Install VcPkg - try: - container.execute("./ns3 configure -- -DNS3_VCPKG=ON") - except DockerException as e: - self.fail() + # Install VcPkg + try: + container.execute("./ns3 configure -- -DNS3_VCPKG=ON") + except DockerException as e: + self.fail() - # Install Armadillo with VcPkg - try: - container.execute("./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG") - except DockerException as e: - self.fail() + # Install Armadillo with VcPkg + try: + container.execute("./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG") + except DockerException as e: + self.fail() - # Try to build module using VcPkg's Armadillo - try: - container.execute("./ns3 build test-package-managers") - except DockerException as e: - self.fail() + # Try to build module using VcPkg's Armadillo + try: + container.execute("./ns3 build test-package-managers") + except DockerException as e: + self.fail() # Remove test module if os.path.exists(destination_src):