Merge commit 'ebb5969' into unison

This commit is contained in:
F5
2023-11-11 21:16:15 +08:00
3033 changed files with 94436 additions and 836752 deletions

View File

@@ -0,0 +1,21 @@
# A list of the modules that will be enabled when ns-3 is run.
# Modules that depend on the listed modules will be enabled also.
#
# All modules can be enabled by emptying the list.
set(ns3rc_enabled_modules @ns3rc_enabled_modules@)
# A list of the modules that will be disabled when ns-3 is run.
# Modules that depend on the listed modules will be disabled also.
#
# If the list is empty, no module will be disabled.
set(ns3rc_disabled_modules @ns3rc_disabled_modules@)
# Set this equal to ON if you want examples to be run.
set(ns3rc_examples_enabled @ns3rc_examples_enabled@)
# Set this equal to ON if you want tests to be run.
set(ns3rc_tests_enabled @ns3rc_tests_enabled@)
# Override other ns-3 settings by setting their values below
# Note: command-line settings will also be overridden.
#set(NS3_LOG ON)

View File

@@ -18,6 +18,8 @@
find_package(Qt4 COMPONENTS QtGui QUIET)
find_package(Qt5 COMPONENTS Core Widgets PrintSupport Gui QUIET)
add_definitions(-Wno-error=misleading-indentation)
if((NOT ${Qt4_FOUND}) AND (NOT ${Qt5_FOUND}))
message(FATAL_ERROR "You need Qt installed to build NetAnim")
endif()
@@ -188,4 +190,4 @@ else()
endif()
target_include_directories(netanim PUBLIC qtpropertybrowser/src)
set_runtime_outputdirectory(netanim ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bin "")
set_runtime_outputdirectory(netanim ${CMAKE_OUTPUT_DIRECTORY}/bin/ "")

View File

@@ -1,4 +1,16 @@
additional_commands:
build_exec:
flags: [IGNORE_PCH, STANDALONE]
kwargs:
EXECNAME : '1'
EXECNAME_PREFIX : '1'
EXECUTABLE_DIRECTORY_PATH : '1'
INSTALL_DIRECTORY_PATH : '1'
SOURCE_FILES : '*'
HEADER_FILES : '*'
LIBRARIES_TO_LINK : '*'
DEFINITIONS : '*'
build_lib:
flags: [IGNORE_PCH]
kwargs:
@@ -19,6 +31,7 @@ additional_commands:
LIBRARIES_TO_LINK : '*'
build_example:
flags: [IGNORE_PCH]
kwargs:
NAME : '1'
SOURCE_FILES : '*'

View File

@@ -1,3 +1,53 @@
additional_commands:
build_exec:
flags: [IGNORE_PCH, STANDALONE]
kwargs:
EXECNAME : '1'
EXECNAME_PREFIX : '1'
EXECUTABLE_DIRECTORY_PATH : '1'
INSTALL_DIRECTORY_PATH : '1'
SOURCE_FILES : '*'
HEADER_FILES : '*'
LIBRARIES_TO_LINK : '*'
DEFINITIONS : '*'
build_lib:
flags: [IGNORE_PCH]
kwargs:
LIBNAME : '1'
SOURCE_FILES : '*'
HEADER_FILES : '*'
LIBRARIES_TO_LINK : '*'
TEST_SOURCES : '*'
DEPRECATED_HEADER_FILES : '*'
MODULE_ENABLED_FEATURES : '*'
build_lib_example:
flags: [IGNORE_PCH]
kwargs:
NAME : '1'
SOURCE_FILES : '*'
HEADER_FILES : '*'
LIBRARIES_TO_LINK : '*'
build_example:
flags: [IGNORE_PCH]
kwargs:
NAME : '1'
SOURCE_FILES : '*'
HEADER_FILES : '*'
LIBRARIES_TO_LINK : '*'
find_external_library:
kwargs:
DEPENDENCY_NAME : '1'
HEADER_NAME : '1'
LIBRARY_NAME : '1'
HEADER_NAMES : '*'
LIBRARY_NAMES : '*'
PATH_SUFFIXES : '*'
SEARCH_PATHS : '*'
format:
tab_size: 2
line_width: 80

View File

@@ -0,0 +1,15 @@
#ifndef OSTREAM_OPERATOR_NULLPTR_H
#define OSTREAM_OPERATOR_NULLPTR_H
#include <iostream>
#include <cstddef>
namespace std
{
inline std::ostream &operator<< (std::ostream &os, std::nullptr_t ptr)
{
return os << "nullptr"; //whatever you want nullptr to show up as in the console
}
}
#endif //OSTREAM_OPERATOR_NULLPTR_H

View File

@@ -15,6 +15,5 @@
#cmakedefine01 HAVE_STDLIB_H
#cmakedefine01 HAVE_GETENV
#cmakedefine01 HAVE_SIGNAL_H
#cmakedefine HAVE_RT
#endif //NS3_CORE_CONFIG_H

View File

@@ -99,6 +99,11 @@ function(pkgconfig_module libname)
# Set file to be installed
install(FILES ${pkgconfig_file} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
add_custom_target(
uninstall_pkgconfig_${module_name}
COMMAND rm ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig/ns3-${module_name}.pc
)
add_dependencies(uninstall uninstall_pkgconfig_${module_name})
endfunction()
function(ns3_cmake_package)
@@ -147,10 +152,24 @@ function(ns3_cmake_package)
endfunction()
# You will need administrative privileges to run this
# cmake-format: off
if(WIN32)
add_custom_target(
uninstall
COMMAND
powershell -Command \" Remove-Item \\"${CMAKE_INSTALL_FULL_LIBDIR}/libns3*\\" -Recurse \" &&
powershell -Command \" Remove-Item \\"${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig/ns3-*\\" -Recurse \" &&
powershell -Command \" Remove-Item \\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/ns3\\" -Recurse \" &&
powershell -Command \" Remove-Item \\"${CMAKE_INSTALL_FULL_INCLUDEDIR}/ns3\\" -Recurse \"
)
else()
add_custom_target(
uninstall
COMMAND
rm `ls ${CMAKE_INSTALL_FULL_LIBDIR}/libns3*` && rm -R
${CMAKE_INSTALL_FULL_LIBDIR}/cmake/ns3 && rm -R
${CMAKE_INSTALL_FULL_INCLUDEDIR}/ns3
rm `ls ${CMAKE_INSTALL_FULL_LIBDIR}/libns3*` &&
rm `ls ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig/ns3-*` &&
rm -R ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/ns3 &&
rm -R ${CMAKE_INSTALL_FULL_INCLUDEDIR}/ns3
)
endif()
# cmake-format: on

View File

@@ -0,0 +1,72 @@
# Copyright (c) 2022 Universidade de Brasília
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 2 as published by the Free
# Software Foundation;
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
include(CheckCXXSourceCompiles)
# Clang 6, 7 and 8 shipped with incomplete C++17 features and do not handle
# ostream& operator<<(ostream& os, nullptr_t ptr)
# https://gitlab.com/nsnam/ns-3-dev/-/issues/730
check_cxx_source_compiles(
"
#include <iostream>
#include <cstddef>
inline std::ostream& operator << (std::ostream& os, std::nullptr_t ptr)
{
return os << \"nullptr\"; //whatever you want nullptr to show up as in the console
}
int main()
{
std::ostream os(NULL);
os << std::nullptr_t();
return 0;
}
"
MISSING_OSTREAM_NULLPTR_OPERATOR
)
if(${MISSING_OSTREAM_NULLPTR_OPERATOR})
message(
${HIGHLIGHTED_STATUS}
"Using compiler workaround: compiling in \"ostream& operator<<(ostream&, nullptr_t)\""
)
add_definitions(
-include
${CMAKE_CURRENT_SOURCE_DIR}/build-support/compiler-workarounds/ostream-operator-nullptr.h
)
endif()
# Some compilers (e.g. GCC < 9.1 and Clang < 9) do not link
# std::filesystem/std::experimental::filesystem by default. If the sample
# program can be linked, it means it is indeed linked by default. Otherwise, we
# link it manually. https://en.cppreference.com/w/cpp/filesystem
check_cxx_source_compiles(
"
# ifdef __cpp_lib_filesystem
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
int main()
{
std::string path = \"/\";
return !fs::exists (path);
}
"
FILESYSTEM_LIBRARY_IS_LINKED
)

View File

@@ -118,6 +118,10 @@ macro(write_configtable)
string(APPEND out
"Build directory : ${CMAKE_OUTPUT_DIRECTORY}\n"
)
string(APPEND out "Build version embedding : ")
check_on_or_off("${NS3_ENABLE_BUILD_VERSION}" "${ENABLE_BUILD_VERSION}")
string(APPEND out "BRITE Integration : ")
check_on_or_off("ON" "${NS3_BRITE}")
@@ -163,17 +167,9 @@ macro(write_configtable)
string(APPEND out "PyViz visualizer : ")
check_on_or_off("${NS3_VISUALIZER}" "${ENABLE_VISUALIZER}")
string(APPEND out "Python API Scanning Support : ")
check_on_or_off(
"${NS3_SCAN_PYTHON_BINDINGS}" "${ENABLE_SCAN_PYTHON_BINDINGS}"
)
string(APPEND out "Python Bindings : ")
check_on_or_off("${NS3_PYTHON_BINDINGS}" "${ENABLE_PYTHON_BINDINGS}")
string(APPEND out "Real Time Simulator : ")
check_on_or_off("${NS3_REALTIME}" "${ENABLE_REALTIME}")
string(APPEND out "SQLite support : ")
check_on_or_off("${NS3_SQLITE}" "${ENABLE_SQLITE}")

View File

@@ -54,12 +54,27 @@ function(write_lock)
endforeach()
string(APPEND lock_contents "]\n")
string(REPLACE ":" "', '" PATH_LIST $ENV{PATH})
string(
APPEND
lock_contents
"NS3_MODULE_PATH = ['${PATH_LIST}', '${CMAKE_OUTPUT_DIRECTORY}', '${CMAKE_LIBRARY_OUTPUT_DIRECTORY}']\n"
# Windows variables are separated with ; which CMake also uses to separate
# list items
set(PATH_LIST
"$ENV{PATH};${CMAKE_OUTPUT_DIRECTORY};${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
)
if(WIN32)
# Windows to unix path conversions can be quite messy, so we replace forward
# slash with double backward slash
string(REPLACE "/" "\\" PATH_LIST "${PATH_LIST}")
# And to print it out, we need to escape these backward slashes with more
# backward slashes
string(REPLACE "\\" "\\\\" PATH_LIST "${PATH_LIST}")
else()
# Unix variables are separated with :
string(REPLACE ":" ";" PATH_LIST "${PATH_LIST}")
endif()
# After getting all entries with their correct paths we replace the ; item
# separator into a Python list of strings written to the lock file
string(REPLACE ";" "', '" PATH_LIST "${PATH_LIST}")
string(APPEND lock_contents "NS3_MODULE_PATH = ['${PATH_LIST}']\n")
cache_cmake_flag(ENABLE_REALTIME "ENABLE_REAL_TIME" lock_contents)
cache_cmake_flag(ENABLE_EXAMPLES "ENABLE_EXAMPLES" lock_contents)
@@ -69,9 +84,6 @@ function(write_lock)
cache_cmake_flag(NS3_BRITE "ENABLE_BRITE" lock_contents)
cache_cmake_flag(NS3_ENABLE_SUDO "ENABLE_SUDO" lock_contents)
cache_cmake_flag(NS3_PYTHON_BINDINGS "ENABLE_PYTHON_BINDINGS" lock_contents)
cache_cmake_flag(
NS3_SCAN_PYTHON_BINDINGS "ENABLE_SCAN_PYTHON_BINDINGS" lock_contents
)
string(APPEND lock_contents "EXAMPLE_DIRECTORIES = [")
foreach(example_folder ${ns3-example-folders})
@@ -82,6 +94,9 @@ function(write_lock)
string(APPEND lock_contents "APPNAME = 'ns'\n")
string(APPEND lock_contents "BUILD_PROFILE = '${build_profile}'\n")
string(APPEND lock_contents "VERSION = '${NS3_VER}' \n")
string(APPEND lock_contents
"BUILD_VERSION_STRING = '${BUILD_VERSION_STRING}' \n"
)
string(APPEND lock_contents "PYTHON = ['${Python3_EXECUTABLE}']\n")
mark_as_advanced(VALGRIND)

View File

@@ -66,7 +66,7 @@ function(build_lib)
"${BLIB_HEADER_FILES}"
)
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${IGNORE_PCH}))
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH}))
target_precompile_headers(${lib${BLIB_LIBNAME}-obj} REUSE_FROM stdlib_pch)
endif()
@@ -80,7 +80,7 @@ function(build_lib)
# specific path for that
add_library(${lib${BLIB_LIBNAME}} SHARED "${BLIB_SOURCE_FILES}")
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${IGNORE_PCH}))
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH}))
target_precompile_headers(${lib${BLIB_LIBNAME}} REUSE_FROM stdlib_pch)
endif()
endif()
@@ -97,12 +97,32 @@ function(build_lib)
${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h
)
endif()
if(NOT FILESYSTEM_LIBRARY_IS_LINKED)
list(APPEND BLIB_LIBRARIES_TO_LINK -lstdc++fs)
endif()
# Enable examples as tests suites
if(${ENABLE_EXAMPLES} AND ${ENABLE_TESTS})
if(NOT ${XCODE})
target_compile_definitions(
${lib${BLIB_LIBNAME}}-obj PRIVATE NS3_ENABLE_EXAMPLES
)
else()
target_compile_definitions(
${lib${BLIB_LIBNAME}} PRIVATE NS3_ENABLE_EXAMPLES
)
endif()
endif()
endif()
set_target_properties(
${lib${BLIB_LIBNAME}}
PROPERTIES
PUBLIC_HEADER
"${BLIB_HEADER_FILES};${BLIB_DEPRECATED_HEADER_FILES};${config_headers};${CMAKE_HEADER_OUTPUT_DIRECTORY}/${BLIB_LIBNAME}-module.h"
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} # set output
# directory for
# DLLs
)
if(${NS3_CLANG_TIMETRACE})
@@ -211,41 +231,58 @@ function(build_lib)
)
endif()
# 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})
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} lib${BLIB_LIBNAME}-test CACHE INTERNAL "")
set(ns3-libs-tests "${test${BLIB_LIBNAME}};${ns3-libs-tests}"
CACHE INTERNAL "list of test libraries"
)
# Create shared library containing tests of the module
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}
# 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
"$<TARGET_OBJECTS:${test${BLIB_LIBNAME}}>;${ns3-libs-tests}"
CACHE INTERNAL "list of test libraries"
)
add_library(${test${BLIB_LIBNAME}} OBJECT "${BLIB_TEST_SOURCES}")
else()
target_link_libraries(
${test${BLIB_LIBNAME}} ${LIB_AS_NEEDED_PRE} ${lib${BLIB_LIBNAME}}
"${BLIB_LIBRARIES_TO_LINK}" ${LIB_AS_NEEDED_POST}
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} ${lib${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()
set_target_properties(
${test${BLIB_LIBNAME}}
PROPERTIES OUTPUT_NAME
ns${NS3_VER}-${BLIB_LIBNAME}-test${build_profile_suffix}
)
target_compile_definitions(
${test${BLIB_LIBNAME}} PRIVATE NS_TEST_SOURCEDIR="${FOLDER}/test"
)
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${IGNORE_PCH}))
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_IGNORE_PCH}))
target_precompile_headers(${test${BLIB_LIBNAME}} REUSE_FROM stdlib_pch)
endif()
endif()
@@ -263,204 +300,13 @@ function(build_lib)
endif()
endforeach()
# Get architecture pair for python bindings
if((${CMAKE_SIZEOF_VOID_P} EQUAL 8) AND (NOT APPLE))
set(arch gcc_LP64)
set(arch_flags -m64)
else()
set(arch gcc_ILP32)
set(arch_flags)
endif()
# Add target to scan python bindings
if(${ENABLE_SCAN_PYTHON_BINDINGS}
AND (EXISTS ${CMAKE_HEADER_OUTPUT_DIRECTORY}/${BLIB_LIBNAME}-module.h)
AND (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/bindings")
)
set(bindings_output_folder ${PROJECT_SOURCE_DIR}/${FOLDER}/bindings)
file(MAKE_DIRECTORY ${bindings_output_folder})
set(module_api_ILP32 ${bindings_output_folder}/modulegen__gcc_ILP32.py)
set(module_api_LP64 ${bindings_output_folder}/modulegen__gcc_LP64.py)
set(modulescan_modular_command
${Python3_EXECUTABLE}
${PROJECT_SOURCE_DIR}/bindings/python/ns3modulescan-modular.py
)
set(header_map "")
# We need a python map that takes header.h to module e.g. "ptr.h": "core"
foreach(header ${BLIB_HEADER_FILES})
# header is a relative path to the current working directory
get_filename_component(
header_name ${CMAKE_CURRENT_SOURCE_DIR}/${header} NAME
)
string(APPEND header_map "\"${header_name}\":\"${BLIB_LIBNAME}\",")
endforeach()
set(ns3-headers-to-module-map "${ns3-headers-to-module-map}${header_map}"
CACHE INTERNAL "Map connecting headers to their modules"
)
# API scan needs the include directories to find a few headers (e.g. mpi.h)
get_target_includes(${lib${BLIB_LIBNAME}} modulegen_include_dirs)
set(module_to_generate_api ${module_api_ILP32})
set(LP64toILP32)
if("${arch}" STREQUAL "gcc_LP64")
set(module_to_generate_api ${module_api_LP64})
set(LP64toILP32
${Python3_EXECUTABLE}
${PROJECT_SOURCE_DIR}/build-support/pybindings-LP64-to-ILP32.py
${module_api_LP64} ${module_api_ILP32}
)
endif()
add_custom_target(
${lib${BLIB_LIBNAME}}-apiscan
COMMAND
${modulescan_modular_command} ${CMAKE_OUTPUT_DIRECTORY} ${BLIB_LIBNAME}
${PROJECT_BINARY_DIR}/header_map.json ${module_to_generate_api}
\"${arch_flags} ${modulegen_include_dirs}\" 2>
${bindings_output_folder}/apiscan.log
COMMAND ${LP64toILP32}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${lib${BLIB_LIBNAME}}
)
add_dependencies(apiscan-all ${lib${BLIB_LIBNAME}}-apiscan)
endif()
# Build pybindings if requested and if bindings subfolder exists in
# NS3/src/BLIB_LIBNAME
if(${ENABLE_PYTHON_BINDINGS} AND (EXISTS
"${CMAKE_CURRENT_SOURCE_DIR}/bindings")
)
set(bindings_output_folder ${CMAKE_OUTPUT_DIRECTORY}/${FOLDER}/bindings)
file(MAKE_DIRECTORY ${bindings_output_folder})
set(module_src ${bindings_output_folder}/ns3module.cc)
set(module_hdr ${bindings_output_folder}/ns3module.h)
string(REPLACE "-" "_" BLIB_LIBNAME_sub ${BLIB_LIBNAME}) # '-' causes
# problems (e.g.
# csma-layout), replace with '_' (e.g. csma_layout)
# Set prefix of binding to _ if a ${BLIB_LIBNAME}.py exists, and copy the
# ${BLIB_LIBNAME}.py to the output folder
set(prefix)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bindings/${BLIB_LIBNAME}.py)
set(prefix _)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/bindings/${BLIB_LIBNAME}.py
DESTINATION ${CMAKE_OUTPUT_DIRECTORY}/bindings/python/ns
)
endif()
# Run modulegen-modular to generate the bindings sources
if((NOT EXISTS ${module_hdr}) OR (NOT EXISTS ${module_src})) # OR TRUE) # to
# force
# reprocessing
string(REPLACE ";" "," ENABLED_FEATURES
"${ns3-libs};${BLIB_MODULE_ENABLED_FEATURES}"
)
set(modulegen_modular_command
GCC_RTTI_ABI_COMPLETE=True NS3_ENABLED_FEATURES="${ENABLED_FEATURES}"
${Python3_EXECUTABLE}
${PROJECT_SOURCE_DIR}/bindings/python/ns3modulegen-modular.py
)
execute_process(
COMMAND
${CMAKE_COMMAND} -E env
PYTHONPATH=${CMAKE_OUTPUT_DIRECTORY}:$ENV{PYTHONPATH}
${modulegen_modular_command} ${CMAKE_CURRENT_SOURCE_DIR} ${arch}
${prefix}${BLIB_LIBNAME_sub} ${module_src}
TIMEOUT 60
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_FILE ${module_hdr}
ERROR_FILE ${bindings_output_folder}/ns3modulegen.log
RESULT_VARIABLE error_code
)
if(${error_code} OR NOT (EXISTS ${module_hdr}))
# Delete broken bindings to make sure we will his this error again if
# nothing changed
if(EXISTS ${module_src})
file(REMOVE ${module_src})
endif()
if(EXISTS ${module_hdr})
file(REMOVE ${module_hdr})
endif()
message(
FATAL_ERROR
"Something went wrong during processing of the python bindings of module ${BLIB_LIBNAME}."
" Make sure you have the latest version of Pybindgen."
)
endif()
endif()
# Add core module helper sources
set(python_module_files ${module_hdr} ${module_src})
file(GLOB custom_python_module_files
${CMAKE_CURRENT_SOURCE_DIR}/bindings/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/bindings/*.h
)
list(APPEND python_module_files ${custom_python_module_files})
set(bindings-name lib${BLIB_LIBNAME}-bindings)
add_library(${bindings-name} SHARED "${python_module_files}")
target_include_directories(
${bindings-name} PUBLIC ${Python3_INCLUDE_DIRS} ${bindings_output_folder}
)
# If there is any, remove the "lib" prefix of libraries (search for
# "set(lib${BLIB_LIBNAME}")
list(LENGTH ns_libraries_to_link num_libraries)
if(num_libraries GREATER "0")
string(REPLACE ";" "-bindings;" bindings_to_link
"${ns_libraries_to_link};"
) # add -bindings suffix to all lib${name}
endif()
target_link_libraries(
${bindings-name}
PUBLIC ${LIB_AS_NEEDED_PRE} ${lib${BLIB_LIBNAME}} "${bindings_to_link}"
"${BLIB_LIBRARIES_TO_LINK}" ${LIB_AS_NEEDED_POST}
PRIVATE ${Python3_LIBRARIES}
)
target_include_directories(
${bindings-name} PRIVATE ${PROJECT_SOURCE_DIR}/src/core/bindings
)
set(suffix)
if(APPLE)
# Python doesn't like Apple's .dylib and will refuse to load bindings
# unless its an .so
set(suffix SUFFIX .so)
endif()
# Set binding library name and output folder
set_target_properties(
${bindings-name}
PROPERTIES OUTPUT_NAME ${prefix}${BLIB_LIBNAME_sub}
PREFIX ""
${suffix} LIBRARY_OUTPUT_DIRECTORY
${CMAKE_OUTPUT_DIRECTORY}/bindings/python/ns
)
set(ns3-python-bindings-modules
"${bindings-name};${ns3-python-bindings-modules}"
CACHE INTERNAL "list of modules python bindings"
)
# Make sure all bindings are built before building the visualizer module
# that makes use of them
if(${ENABLE_VISUALIZER} AND (visualizer IN_LIST libs_to_build))
if(NOT (${BLIB_LIBNAME} STREQUAL visualizer))
add_dependencies(${libvisualizer} ${bindings-name})
endif()
endif()
endif()
# Handle package export
install(
TARGETS ${lib${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"
)
if(${NS3_VERBOSE})
@@ -493,38 +339,34 @@ function(build_lib_example)
check_for_missing_libraries(
missing_dependencies "${BLIB_EXAMPLE_LIBRARIES_TO_LINK}"
)
if(NOT missing_dependencies)
# Create shared library with sources and headers
add_executable(
"${BLIB_EXAMPLE_NAME}" ${BLIB_EXAMPLE_SOURCE_FILES}
${BLIB_EXAMPLE_HEADER_FILES}
)
if(${NS3_STATIC})
target_link_libraries(
${BLIB_EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE_STATIC} ${lib-ns3-static}
)
elseif(${NS3_MONOLIB})
target_link_libraries(
${BLIB_EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE} ${lib-ns3-monolib}
${LIB_AS_NEEDED_POST}
)
else()
target_link_libraries(
${BLIB_EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE} ${lib${BLIB_EXAMPLE_LIBNAME}}
${BLIB_EXAMPLE_LIBRARIES_TO_LINK} ${optional_visualizer_lib}
${LIB_AS_NEEDED_POST}
)
# 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()
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BLIB_EXAMPLE_IGNORE_PCH}))
target_precompile_headers(${BLIB_EXAMPLE_NAME} REUSE_FROM stdlib_pch_exec)
if((NOT missing_dependencies) AND ${filtered_in})
# Convert boolean into text to forward argument
if(${BLIB_EXAMPLE_IGNORE_PCH})
set(IGNORE_PCH IGNORE_PCH)
endif()
set_runtime_outputdirectory(
${BLIB_EXAMPLE_NAME}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${FOLDER}/ ""
# Create executable with sources and headers
# cmake-format: off
build_exec(
EXECNAME ${BLIB_EXAMPLE_NAME}
SOURCE_FILES ${BLIB_EXAMPLE_SOURCE_FILES}
HEADER_FILES ${BLIB_EXAMPLE_HEADER_FILES}
LIBRARIES_TO_LINK
${lib${BLIB_LIBNAME}} ${BLIB_EXAMPLE_LIBRARIES_TO_LINK}
${optional_visualizer_lib}
EXECUTABLE_DIRECTORY_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${FOLDER}/
${IGNORE_PCH}
)
# cmake-format: on
endif()
endfunction()

View File

@@ -76,35 +76,27 @@ function(configure_embedded_version)
check-version COMMAND echo Build version feature disabled. Reconfigure
ns-3 with NS3_ENABLE_BUILD_VERSION=ON
)
set(BUILD_VERSION_STRING PARENT_SCOPE)
return()
endif()
set(HAS_NS3_TAGS False)
mark_as_advanced(GIT)
find_program(GIT git)
if("${GIT}" STREQUAL "GIT-NOTFOUND")
message(
STATUS "Git was not found. Version related targets won't be enabled"
STATUS
"Git was not found. Build version embedding won't be enabled if version.cache is not found."
)
return()
else()
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
# If the git history exists, check if ns-3 git tags were found
check_git_repo_has_ns3_tags(HAS_NS3_TAGS NS3_VERSION_TAG)
endif()
endif()
check_git_repo_has_ns3_tags(HAS_NS3_TAGS NS3_VERSION_TAG)
set(version_cache_file_template
${PROJECT_SOURCE_DIR}/build-support/version.cache.in
)
set(version_cache_file ${PROJECT_SOURCE_DIR}/src/core/model/version.cache)
# Check if ns-3 git tags were found or at least version.cache file exists in
# the src/core/model
if((NOT HAS_NS3_TAGS) AND (NOT (EXISTS ${version_cache_file})))
message(
FATAL_ERROR
"The ns-3 git commit history or the version.cache file are required to embed build version into libraries."
)
return()
endif()
# If git tags were found, extract the information
if(HAS_NS3_TAGS)
check_ns3_closest_tags(
@@ -134,7 +126,7 @@ function(configure_embedded_version)
if(${VER_LIST_LEN} GREATER 2)
list(GET VERSION_LIST 2 NS3_VERSION_PATCH)
else()
set(NS3_VERSION_PATCH "00")
set(NS3_VERSION_PATCH "0")
endif()
endif()
@@ -149,9 +141,24 @@ function(configure_embedded_version)
endif()
set(NS3_VERSION_BUILD_PROFILE ${cmakeBuildType})
set(version_cache_file_template
${PROJECT_SOURCE_DIR}/build-support/version.cache.in
)
# Create version.cache file
configure_file(${version_cache_file_template} ${version_cache_file} @ONLY)
else()
# If we could not find the Git executable, or there were not ns-3 tags in
# the git history, we fallback to the version.cache file
if(EXISTS ${version_cache_file})
message(STATUS "The version.cache file was found.")
else()
message(
FATAL_ERROR
"The version.cache file was not found and is required to embed the build version."
)
endif()
# Consume version.cache created previously
file(STRINGS ${version_cache_file} version_cache_contents)
foreach(line ${version_cache_contents})
@@ -173,7 +180,7 @@ function(configure_embedded_version)
# If value is empty, replace with an empty string, assume its the release
# candidate string
if(NOT varvalue)
if((NOT varvalue) AND (NOT varvalue STREQUAL "0"))
set(varvalue "\"\"")
endif()
@@ -195,6 +202,7 @@ function(configure_embedded_version)
)
string(REPLACE "\"" "" version "${version}")
add_custom_target(check-version COMMAND echo ns-3 version: ${version})
set(BUILD_VERSION_STRING ${version} PARENT_SCOPE)
# Enable embedding build version
add_definitions(-DENABLE_BUILD_VERSION=1)

View File

@@ -1 +1 @@
int main(){}
int main(){}

View File

@@ -43,7 +43,7 @@ include(${PROJECT_SOURCE_DIR}/build-support/3rd-party/colored-messages.cmake)
# WSLv1 doesn't support tap features
if(EXISTS "/proc/version")
file(READ "/proc/version" CMAKE_LINUX_DISTRO)
string(FIND ${CMAKE_LINUX_DISTRO} "Microsoft" res)
string(FIND "${CMAKE_LINUX_DISTRO}" "Microsoft" res)
if(res EQUAL -1)
set(WSLv1 False)
else()
@@ -61,6 +61,12 @@ if(APPLE)
add_definitions(-D__APPLE__)
endif()
if(WIN32)
set(NS3_PRECOMPILE_HEADERS OFF
CACHE BOOL "Precompile module headers to speed up compilation" FORCE
)
endif()
set(cat_command cat)
if(CMAKE_XCODE_BUILD_SYSTEM)
@@ -86,6 +92,13 @@ else()
"${PROJECT_SOURCE_DIR}/${NS3_OUTPUT_DIRECTORY}"
)
endif()
# Transform backward slash into forward slash Not the best way to do it since
# \ is a scape thing and can be used before whitespaces
string(REPLACE "\\" "/" absolute_ns3_output_directory
"${absolute_ns3_output_directory}"
)
if(NOT (EXISTS ${absolute_ns3_output_directory}))
message(
STATUS
@@ -204,6 +217,7 @@ set(CMAKE_CXX_STANDARD_MINIMUM 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(LIB_AS_NEEDED_PRE)
set(LIB_AS_NEEDED_POST)
set(STATIC_LINK_FLAGS -static -static-libstdc++ -static-libgcc)
if(${GCC} AND NOT APPLE)
# using GCC
set(LIB_AS_NEEDED_PRE -Wl,--no-as-needed)
@@ -216,8 +230,46 @@ endif()
if(${CLANG} AND APPLE)
# using Clang set(LIB_AS_NEEDED_PRE -all_load)
set(LIB_AS_NEEDED_POST)
set(LIB_AS_NEEDED_PRE_STATIC -Wl,-all_load)
set(STATIC_LINK_FLAGS)
endif()
# Search for faster linkers mold and lld, and use them if available
mark_as_advanced(MOLD LLD)
find_program(MOLD mold)
find_program(LLD ld.lld)
# USING_FAST_LINKER will be defined if a fast linker is being used and its
# content will correspond to the fast linker name
# Mold support was added in GCC 12.1.0
if(NOT USING_FAST_LINKER
AND NOT (${MOLD} STREQUAL "MOLD-NOTFOUND")
AND LINUX
AND ${GCC}
AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.1.0)
)
set(USING_FAST_LINKER MOLD)
add_link_options("-fuse-ld=mold")
endif()
if(NOT USING_FAST_LINKER AND NOT (${LLD} STREQUAL "LLD-NOTFOUND")
AND (${GCC} OR ${CLANG})
)
set(USING_FAST_LINKER LLD)
add_link_options("-fuse-ld=lld")
if(WIN32)
# Clear unsupported linker flags on Windows
set(LIB_AS_NEEDED_PRE)
endif()
endif()
# Include CMake files used for compiler checks
include(CheckIncludeFile) # Used to check a single C header at a time
include(CheckIncludeFileCXX) # Used to check a single C++ header at a time
include(CheckIncludeFiles) # Used to check multiple headers at once
include(CheckFunctionExists)
macro(SUBDIRLIST result curdir)
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
@@ -350,6 +402,16 @@ macro(process_options)
set(build_profile_suffix -${build_profile} CACHE INTERNAL "")
endif()
if(${NS3_VERBOSE})
set_property(GLOBAL PROPERTY TARGET_MESSAGES TRUE)
set(CMAKE_FIND_DEBUG_MODE TRUE)
set(CMAKE_VERBOSE_MAKEFILE TRUE CACHE INTERNAL "")
else()
set_property(GLOBAL PROPERTY TARGET_MESSAGES OFF)
unset(CMAKE_FIND_DEBUG_MODE)
unset(CMAKE_VERBOSE_MAKEFILE CACHE)
endif()
# Set warning level and warning as errors
if(${NS3_WARNINGS})
if(MSVC)
@@ -403,6 +465,8 @@ macro(process_options)
else()
set(CMAKE_CXX_CLANG_TIDY "clang-tidy")
endif()
else()
unset(CMAKE_CXX_CLANG_TIDY)
endif()
if(${NS3_CLANG_TIMETRACE})
@@ -485,6 +549,15 @@ macro(process_options)
)
endif()
# Honor CMAKE_CXX_STANDARD in check_cxx_source_compiles
# https://cmake.org/cmake/help/latest/policy/CMP0067.html
cmake_policy(SET CMP0066 NEW)
cmake_policy(SET CMP0067 NEW)
# After setting the correct CXX version, we can proceed to check for compiler
# workarounds
include(build-support/custom-modules/ns3-compiler-workarounds.cmake)
if(${NS3_DES_METRICS})
add_definitions(-DENABLE_DES_METRICS)
endif()
@@ -647,13 +720,16 @@ macro(process_options)
if(${NS3_STATIC})
# Warn users that they may be using shared libraries, which won't produce a
# standalone static library
set(ENABLE_REALTIME FALSE)
set(HAVE_RT FALSE)
message(
WARNING "Statically linking 3rd party libraries have not been tested.\n"
"Disable Brite, Click, Gtk, GSL, Mpi, Openflow and SQLite"
" if you want a standalone static ns-3 library."
)
if(WIN32)
message(FATAL_ERROR "Static builds are unsupported on Windows"
"\nSocket libraries cannot be linked statically"
)
endif()
else()
find_package(LibXml2 QUIET)
if(NOT ${LIBXML2_FOUND})
@@ -665,26 +741,6 @@ macro(process_options)
add_definitions(-DHAVE_LIBXML2)
include_directories(${LIBXML2_INCLUDE_DIR})
endif()
# LibRT
mark_as_advanced(LIBRT)
set(ENABLE_REALTIME FALSE)
if(${NS3_REALTIME})
if(APPLE)
message(
STATUS "Lib RT is not supported on Mac OS X. Continuing without it."
)
else()
find_library(LIBRT rt QUIET)
if(NOT ${LIBRT_FOUND})
message(FATAL_ERROR "LibRT was not found.")
else()
message(STATUS "LibRT was found.")
set(ENABLE_REALTIME TRUE)
set(HAVE_RT TRUE) # for core-config.h
endif()
endif()
endif()
endif()
set(THREADS_PREFER_PTHREAD_FLAG)
@@ -756,24 +812,26 @@ macro(process_options)
if(${NS3_PYTHON_BINDINGS})
if(NOT ${Python3_FOUND})
message(
FATAL_ERROR
"Bindings: python bindings require Python, but it could not be found"
${HIGHLIGHTED_STATUS}
"Bindings: python bindings require Python, but it could not be found"
)
else()
check_python_packages("pybindgen" missing_packages)
check_python_packages("cppyy" missing_packages)
if(missing_packages)
message(
FATAL_ERROR
"Bindings: python bindings disabled due to the following missing dependencies: ${missing_packages}"
${HIGHLIGHTED_STATUS}
"Bindings: python bindings disabled due to the following missing dependencies: ${missing_packages}"
)
else()
set(ENABLE_PYTHON_BINDINGS ON)
set(destination_dir ${CMAKE_OUTPUT_DIRECTORY}/bindings/python/ns)
configure_file(
bindings/python/ns__init__.py ${destination_dir}/__init__.py COPYONLY
)
endif()
# Copy the bindings file if we have python, which will prevent python
# scripts from failing due to the missing ns package
set(destination_dir ${CMAKE_OUTPUT_DIRECTORY}/bindings/python/ns)
configure_file(
bindings/python/ns__init__.py ${destination_dir}/__init__.py COPYONLY
)
endif()
endif()
@@ -784,44 +842,6 @@ macro(process_options)
add_compile_options(-Wno-potentially-evaluated-expression)
endif()
set(ENABLE_SCAN_PYTHON_BINDINGS OFF)
if(${NS3_SCAN_PYTHON_BINDINGS})
if(NOT ${Python3_FOUND})
message(
FATAL_ERROR
"Bindings: scanning python bindings require Python, but it could not be found"
)
else()
# Check if pybindgen, pygccxml, cxxfilt and castxml are installed
check_python_packages(
"pybindgen;pygccxml;cxxfilt;castxml" missing_packages
)
# If castxml has not been found via python import, fallback to searching
# the binary
if(castxml IN_LIST missing_packages)
mark_as_advanced(CASTXML)
find_program(CASTXML castxml)
if(NOT ("${CASTXML}" STREQUAL "CASTXML-NOTFOUND"))
list(REMOVE_ITEM missing_packages castxml)
endif()
endif()
# If packages were not found, print message
if(missing_packages)
message(
FATAL_ERROR
"Bindings: scanning of python bindings disabled due to the following missing dependencies: ${missing_packages}"
)
else()
set(ENABLE_SCAN_PYTHON_BINDINGS ON)
# empty scan target that will depend on other module scan targets to
# scan all of them
add_custom_target(apiscan-all)
endif()
endif()
endif()
set(ENABLE_VISUALIZER FALSE)
if(${NS3_VISUALIZER})
if((NOT ${ENABLE_PYTHON_BINDINGS}) OR (NOT ${Python3_FOUND}))
@@ -925,7 +945,7 @@ macro(process_options)
# First we check for doxygen dependencies
mark_as_advanced(DOXYGEN)
check_deps("" "doxygen;dot;dia" doxygen_docs_missing_deps)
check_deps("" "doxygen;dot;dia;python3" doxygen_docs_missing_deps)
if(doxygen_docs_missing_deps)
message(
${HIGHLIGHTED_STATUS}
@@ -976,27 +996,28 @@ macro(process_options)
)
file(
WRITE ${PROJECT_SOURCE_DIR}/doc/introspected-command-line.h
WRITE ${CMAKE_BINARY_DIR}/introspected-command-line-preamble.h
"/* This file is automatically generated by
CommandLine::PrintDoxygenUsage() from the CommandLine configuration
in various example programs. Do not edit this file! Edit the
CommandLine configuration in those files instead.
*/
\n"
*/\n"
)
add_custom_target(
assemble-introspected-command-line
# works on CMake 3.18 or newer > COMMAND ${CMAKE_COMMAND} -E cat
# ${PROJECT_SOURCE_DIR}/testpy-output/*.command-line >
# ${PROJECT_SOURCE_DIR}/doc/introspected-command-line.h
COMMAND ${cat_command} ${PROJECT_SOURCE_DIR}/testpy-output/*.command-line
> ${PROJECT_SOURCE_DIR}/doc/introspected-command-line.h 2> NULL
COMMAND
${cat_command} ${CMAKE_BINARY_DIR}/introspected-command-line-preamble.h
${PROJECT_SOURCE_DIR}/testpy-output/*.command-line >
${PROJECT_SOURCE_DIR}/doc/introspected-command-line.h 2> NULL
DEPENDS run-introspected-command-line
)
add_custom_target(
update_doxygen_version
COMMAND ${PROJECT_SOURCE_DIR}/doc/ns3_html_theme/get_version.sh
COMMAND bash ${PROJECT_SOURCE_DIR}/doc/ns3_html_theme/get_version.sh
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
@@ -1050,12 +1071,42 @@ macro(process_options)
add_custom_target(sphinx_contributing COMMAND ${sphinx_missing_msg})
else()
add_custom_target(sphinx COMMENT "Building sphinx documents")
mark_as_advanced(MAKE)
find_program(MAKE NAMES make mingw32-make)
if(${MAKE} STREQUAL "MAKE-NOTFOUND")
message(
FATAL_ERROR "Make was not found but it is required by Sphinx docs"
)
elseif(${MAKE} MATCHES "mingw32-make")
# This is a super wild hack for MinGW
#
# For some reason make is shipped as mingw32-make instead of make, but
# tons of software rely on it being called make
#
# We could technically create an alias, using doskey make=mingw32-make,
# but we need to redefine that for every new shell or make registry
# changes to make it permanent
#
# Symlinking requires administrative permissions for some reason, so we
# just copy the entire thing
get_filename_component(make_directory ${MAKE} DIRECTORY)
get_filename_component(make_parent_directory ${make_directory} DIRECTORY)
if(NOT (EXISTS ${make_directory}/make.exe))
file(COPY ${MAKE} DESTINATION ${make_parent_directory})
file(RENAME ${make_parent_directory}/mingw32-make.exe
${make_directory}/make.exe
)
endif()
set(MAKE ${make_directory}/make.exe)
else()
endif()
function(sphinx_target targetname)
# cmake-format: off
add_custom_target(
sphinx_${targetname}
COMMAND make SPHINXOPTS=-N -k html singlehtml latexpdf
COMMAND ${MAKE} SPHINXOPTS=-N -k html singlehtml latexpdf
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/doc/${targetname}
)
# cmake-format: on
@@ -1129,20 +1180,16 @@ macro(process_options)
set(INT64X64_USE_CAIRO TRUE)
endif()
include(CheckIncludeFileCXX) # Used to check a single header at a time
include(CheckIncludeFiles) # Used to check multiple headers at once
include(CheckFunctionExists)
# Check for required headers and functions, set flags if they're found or warn
# if they're not found
check_include_file_cxx("stdint.h" "HAVE_STDINT_H")
check_include_file_cxx("inttypes.h" "HAVE_INTTYPES_H")
check_include_file_cxx("sys/types.h" "HAVE_SYS_TYPES_H")
check_include_file_cxx("sys/stat.h" "HAVE_SYS_STAT_H")
check_include_file_cxx("dirent.h" "HAVE_DIRENT_H")
check_include_file_cxx("stdlib.h" "HAVE_STDLIB_H")
check_include_file_cxx("signal.h" "HAVE_SIGNAL_H")
check_include_file_cxx("netpacket/packet.h" "HAVE_PACKETH")
check_include_file("stdint.h" "HAVE_STDINT_H")
check_include_file("inttypes.h" "HAVE_INTTYPES_H")
check_include_file("sys/types.h" "HAVE_SYS_TYPES_H")
check_include_file("sys/stat.h" "HAVE_SYS_STAT_H")
check_include_file("dirent.h" "HAVE_DIRENT_H")
check_include_file("stdlib.h" "HAVE_STDLIB_H")
check_include_file("signal.h" "HAVE_SIGNAL_H")
check_include_file("netpacket/packet.h" "HAVE_PACKETH")
check_function_exists("getenv" "HAVE_GETENV")
configure_file(
@@ -1161,12 +1208,6 @@ macro(process_options)
add_definitions(-DNS3_ASSERT_ENABLE)
endif()
# Enable examples as tests suites
if(${ENABLE_EXAMPLES})
set(NS3_ENABLE_EXAMPLES "1")
add_definitions(-DNS3_ENABLE_EXAMPLES -DCMAKE_EXAMPLE_AS_TEST)
endif()
set(ENABLE_TAP OFF)
if(${NS3_TAP})
set(ENABLE_TAP ON)
@@ -1181,7 +1222,7 @@ macro(process_options)
set(PLATFORM_UNSUPPORTED_POST "features. Continuing without them.")
# Remove from libs_to_build all incompatible libraries or the ones that
# dependencies couldn't be installed
if(APPLE OR WSLv1)
if(APPLE OR WSLv1 OR WIN32)
set(ENABLE_TAP OFF)
set(ENABLE_EMU OFF)
list(REMOVE_ITEM libs_to_build fd-net-device)
@@ -1233,7 +1274,12 @@ macro(process_options)
set(PRECOMPILE_HEADERS_ENABLED OFF)
if(${NS3_PRECOMPILE_HEADERS})
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
if(${NS3_CLANG_TIDY})
message(
${HIGHLIGHTED_STATUS}
"Clang-tidy is incompatible with precompiled headers. Continuing without them."
)
elseif(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
set(PRECOMPILE_HEADERS_ENABLED ON)
message(STATUS "Precompiled headers were enabled")
else()
@@ -1245,24 +1291,36 @@ macro(process_options)
endif()
if(${PRECOMPILE_HEADERS_ENABLED})
if(CLANG)
# Clang adds a timestamp to the PCH, which prevents ccache from working
# correctly
# https://github.com/ccache/ccache/issues/539#issuecomment-664198545
add_definitions(-Xclang -fno-pch-timestamp)
endif()
if(${XCODE})
# XCode is weird and messes up with the PCH, requiring this flag
# https://github.com/ccache/ccache/issues/156
add_definitions(-Xclang -fno-validate-pch)
endif()
set(precompiled_header_libraries
<iostream>
<stdint.h>
<stdlib.h>
<map>
<unordered_map>
<vector>
<list>
<algorithm>
<string>
<cstdlib>
<cstring>
<exception>
<fstream>
<iostream>
<limits>
<list>
<map>
<math.h>
<ostream>
<set>
<sstream>
<fstream>
<cstdlib>
<exception>
<cstring>
<limits>
<math.h>
<stdint.h>
<stdlib.h>
<string>
<unordered_map>
<vector>
)
add_library(stdlib_pch OBJECT ${PROJECT_SOURCE_DIR}/build-support/empty.cc)
target_precompile_headers(
@@ -1302,11 +1360,15 @@ macro(process_options)
file(RENAME ${netanim_SOURCE_DIR}/netanim-cmakelists.cmake
${netanim_SOURCE_DIR}/CMakeLists.txt
)
add_subdirectory(${netanim_SOURCE_DIR})
add_subdirectory(${netanim_SOURCE_DIR} ${netanim_BINARY_DIR})
endif()
endmacro()
function(set_runtime_outputdirectory target_name output_directory target_prefix)
# Prevent duplicate '/' in EXECUTABLE_DIRECTORY_PATH, since it gets translated
# to doubled underlines and will cause the ns3 script to fail
string(REPLACE "//" "/" output_directory "${output_directory}")
set(ns3-exec-outputname ns${NS3_VER}-${target_name}${build_profile_suffix})
set(ns3-execs "${output_directory}${ns3-exec-outputname};${ns3-execs}"
CACHE INTERNAL "list of c++ executables"
@@ -1356,6 +1418,73 @@ function(set_runtime_outputdirectory target_name output_directory target_prefix)
endif()
endfunction(set_runtime_outputdirectory)
function(build_exec)
# Argument parsing
set(options IGNORE_PCH STANDALONE)
set(oneValueArgs EXECNAME EXECNAME_PREFIX EXECUTABLE_DIRECTORY_PATH
INSTALL_DIRECTORY_PATH
)
set(multiValueArgs SOURCE_FILES HEADER_FILES LIBRARIES_TO_LINK DEFINITIONS)
cmake_parse_arguments(
"BEXEC" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}
)
add_executable(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} "${BEXEC_SOURCE_FILES}"
)
target_compile_definitions(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} PUBLIC ${BEXEC_DEFINITIONS}
)
if(${PRECOMPILE_HEADERS_ENABLED} AND (NOT ${BEXEC_IGNORE_PCH}))
target_precompile_headers(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} REUSE_FROM stdlib_pch_exec
)
endif()
if(${NS3_STATIC} AND (NOT BEXEC_STANDALONE))
target_link_libraries(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${LIB_AS_NEEDED_PRE_STATIC}
${lib-ns3-static}
)
elseif(${NS3_MONOLIB} AND (NOT BEXEC_STANDALONE))
target_link_libraries(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${LIB_AS_NEEDED_PRE}
${lib-ns3-monolib} ${LIB_AS_NEEDED_POST}
)
else()
target_link_libraries(
${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${LIB_AS_NEEDED_PRE}
"${BEXEC_LIBRARIES_TO_LINK}" ${LIB_AS_NEEDED_POST}
)
endif()
set_runtime_outputdirectory(
"${BEXEC_EXECNAME}" "${BEXEC_EXECUTABLE_DIRECTORY_PATH}/"
"${BEXEC_EXECNAME_PREFIX}"
)
if(BEXEC_INSTALL_DIRECTORY_PATH)
install(TARGETS ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME}
EXPORT ns3ExportTargets
RUNTIME DESTINATION ${BEXEC_INSTALL_DIRECTORY_PATH}
)
get_property(
filename TARGET ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME}
PROPERTY RUNTIME_OUTPUT_NAME
)
add_custom_target(
uninstall_${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME}
COMMAND
rm ${CMAKE_INSTALL_PREFIX}/${BEXEC_INSTALL_DIRECTORY_PATH}/${filename}
)
add_dependencies(
uninstall uninstall_${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME}
)
endif()
endfunction(build_exec)
function(scan_python_examples path)
# Skip python examples search in case the bindings are disabled
if(NOT ${ENABLE_PYTHON_BINDINGS})
@@ -1375,8 +1504,6 @@ endfunction()
add_custom_target(copy_all_headers)
function(copy_headers_before_building_lib libname outputdir headers visibility)
# cmake-format: off
set(batch_symlinks)
foreach(header ${headers})
# Copy header to output directory on changes -> too darn slow
# configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${header} ${outputdir}/
@@ -1386,43 +1513,25 @@ function(copy_headers_before_building_lib libname outputdir headers visibility)
header_name ${CMAKE_CURRENT_SOURCE_DIR}/${header} NAME
)
# If output directory does not exist, create it
if(NOT (EXISTS ${outputdir}))
file(MAKE_DIRECTORY ${outputdir})
endif()
# If header already exists, skip symlinking/stub header creation
if(EXISTS ${outputdir}/${header_name})
continue()
endif()
# CMake 3.13 cannot create symlinks on Windows, so we use stub headers as a
# fallback
if(WIN32 AND (${CMAKE_VERSION} VERSION_LESS "3.13.0"))
# Create a stub header in the output directory, including the real header
# inside their respective module
file(WRITE ${outputdir}/${header_name}
"#include \"${CMAKE_CURRENT_SOURCE_DIR}/${header}\"\n"
)
else()
# Create a symlink in the output directory to the original header Calling
# execute_process for each symlink is too slow too, so we create a batch
# with all headers execute_process(COMMAND ${CMAKE_COMMAND} -E
# create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/${header}
# ${outputdir}/${header_name})
set(batch_symlinks
${batch_symlinks}
COMMAND
${CMAKE_COMMAND}
-E
create_symlink
${CMAKE_CURRENT_SOURCE_DIR}/${header}
${outputdir}/${header_name}
)
endif()
# Create a stub header in the output directory, including the real header
# inside their respective module
get_filename_component(
ABSOLUTE_HEADER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${header}" ABSOLUTE
)
file(WRITE ${outputdir}/${header_name}
"#include \"${ABSOLUTE_HEADER_PATH}\"\n"
)
endforeach()
# Create all symlinks in a single call if there is a symlink to be done
if(batch_symlinks)
execute_process(${batch_symlinks})
endif()
# cmake-format: on
endfunction(copy_headers_before_building_lib)
function(remove_lib_prefix prefixed_library library)
@@ -1475,48 +1584,45 @@ include(build-support/custom-modules/ns3-contributions.cmake)
# Macro to build examples in ns-3-dev/examples/
macro(build_example)
set(options)
set(options IGNORE_PCH)
set(oneValueArgs NAME)
set(multiValueArgs SOURCE_FILES HEADER_FILES LIBRARIES_TO_LINK)
cmake_parse_arguments(
"EXAMPLE" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}
)
# Filter examples out if they don't contain one of the filtered in modules
set(filtered_in ON)
if(NS3_FILTER_MODULE_EXAMPLES_AND_TESTS)
set(filtered_in OFF)
foreach(filtered_module NS3_FILTER_MODULE_EXAMPLES_AND_TESTS)
if(${filtered_module} IN_LIST EXAMPLE_LIBRARIES_TO_LINK)
set(filtered_in ON)
endif()
endforeach()
endif()
check_for_missing_libraries(
missing_dependencies "${EXAMPLE_LIBRARIES_TO_LINK}"
)
if(NOT missing_dependencies)
# Create shared library with sources and headers
add_executable(
${EXAMPLE_NAME} "${EXAMPLE_SOURCE_FILES}" "${EXAMPLE_HEADER_FILES}"
)
if(${NS3_STATIC})
target_link_libraries(
${EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE_STATIC} ${lib-ns3-static}
)
elseif(${NS3_MONOLIB})
target_link_libraries(
${EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE} ${lib-ns3-monolib}
${LIB_AS_NEEDED_POST}
)
else()
# Link the shared library with the libraries passed
target_link_libraries(
${EXAMPLE_NAME} ${LIB_AS_NEEDED_PRE} ${EXAMPLE_LIBRARIES_TO_LINK}
${optional_visualizer_lib} ${LIB_AS_NEEDED_POST}
)
if((NOT missing_dependencies) AND ${filtered_in})
# Convert boolean into text to forward argument
if(${EXAMPLE_IGNORE_PCH})
set(IGNORE_PCH IGNORE_PCH)
endif()
if(${PRECOMPILE_HEADERS_ENABLED})
target_precompile_headers(${EXAMPLE_NAME} REUSE_FROM stdlib_pch_exec)
endif()
set_runtime_outputdirectory(
${EXAMPLE_NAME}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/examples/${examplefolder}/ ""
# Create example library with sources and headers
# cmake-format: off
build_exec(
EXECNAME ${EXAMPLE_NAME}
SOURCE_FILES ${EXAMPLE_SOURCE_FILES}
HEADER_FILES ${EXAMPLE_HEADER_FILES}
LIBRARIES_TO_LINK ${EXAMPLE_LIBRARIES_TO_LINK} ${optional_visualizer_lib}
EXECUTABLE_DIRECTORY_PATH
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/examples/${examplefolder}/
${IGNORE_PCH}
)
# cmake-format: on
endif()
endmacro()
@@ -1618,8 +1724,14 @@ function(recursive_dependency module_name)
endforeach()
endfunction()
macro(filter_enabled_and_disabled_modules libs_to_build contrib_libs_to_build
NS3_ENABLED_MODULES NS3_DISABLED_MODULES ns3rc_enabled_modules
macro(
filter_enabled_and_disabled_modules
libs_to_build
contrib_libs_to_build
NS3_ENABLED_MODULES
NS3_DISABLED_MODULES
ns3rc_enabled_modules
ns3rc_disabled_modules
)
mark_as_advanced(ns3-all-enabled-modules)
@@ -1666,7 +1778,14 @@ macro(filter_enabled_and_disabled_modules libs_to_build contrib_libs_to_build
endif()
endif()
if(${NS3_DISABLED_MODULES})
if(${NS3_DISABLED_MODULES} OR ${ns3rc_disabled_modules})
# List of disabled modules passed by the command line overwrites list read
# from ns3rc
if(${NS3_DISABLED_MODULES})
set(ns3rc_disabled_modules ${${NS3_DISABLED_MODULES}})
endif()
set(all_libs ${${libs_to_build}};${${contrib_libs_to_build}})
# We then use the recursive dependency finding to get all dependencies of
@@ -1679,7 +1798,7 @@ macro(filter_enabled_and_disabled_modules libs_to_build contrib_libs_to_build
endforeach()
# Now we can begin removing libraries that require disabled dependencies
set(disabled_libs "${${NS3_DISABLED_MODULES}}")
set(disabled_libs "${${ns3rc_disabled_modules}}")
foreach(libo ${all_libs})
foreach(lib ${all_libs})
foreach(disabled_lib ${disabled_libs})
@@ -1725,61 +1844,98 @@ macro(filter_enabled_and_disabled_modules libs_to_build contrib_libs_to_build
endmacro()
# Parse .ns3rc
function(parse_ns3rc enabled_modules examples_enabled tests_enabled)
set(ns3rc ${PROJECT_SOURCE_DIR}/.ns3rc)
# Set parent scope variables with default values (all modules, no examples nor
# tests)
set(${enabled_modules} "" PARENT_SCOPE)
set(${examples_enabled} "FALSE" PARENT_SCOPE)
set(${tests_enabled} "FALSE" PARENT_SCOPE)
if(EXISTS ${ns3rc})
# If ns3rc exists in ns-3-dev, read it
file(READ ${ns3rc} ns3rc_contents)
macro(parse_ns3rc enabled_modules disabled_modules examples_enabled
tests_enabled
)
# Try to find .ns3rc
find_file(NS3RC .ns3rc PATHS /etc $ENV{HOME} $ENV{USERPROFILE}
${PROJECT_SOURCE_DIR} NO_CACHE
)
# Match modules_enabled list
if(ns3rc_contents MATCHES "modules_enabled.*\\[(.*).*\\]")
set(${enabled_modules} ${CMAKE_MATCH_1})
if(${enabled_modules} MATCHES "all_modules")
# If all modules, just clean the filter and all modules will get built
# by default
set(${enabled_modules})
else()
# If modules are listed, remove quotes and replace commas with
# semicolons transforming a string into a cmake list
string(REPLACE "," ";" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "'" "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "\"" "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE " " "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "\n" ";" ${enabled_modules} "${${enabled_modules}}")
list(SORT ${enabled_modules})
# Set variables with default values (all modules, no examples nor tests)
set(${enabled_modules} "")
set(${disabled_modules} "")
set(${examples_enabled} "FALSE")
set(${tests_enabled} "FALSE")
# Remove possibly empty entry
list(REMOVE_ITEM ${enabled_modules} "")
foreach(element ${${enabled_modules}})
# Inspect each element for comments
if(${element} MATCHES "#.*")
list(REMOVE_ITEM ${enabled_modules} ${element})
endif()
endforeach()
endif()
if(NOT (${NS3RC} STREQUAL "NS3RC-NOTFOUND"))
message(${HIGHLIGHTED_STATUS}
"Configuration file .ns3rc being used : ${NS3RC}"
)
file(READ ${NS3RC} ns3rc_contents)
# Check if ns3rc file is CMake or Python based and act accordingly
if(ns3rc_contents MATCHES "ns3rc_*")
include(${NS3RC})
else()
parse_python_ns3rc(
"${ns3rc_contents}" ${enabled_modules} ${examples_enabled}
${tests_enabled} ${NS3RC}
)
endif()
# Match examples_enabled flag
if(ns3rc_contents MATCHES "examples_enabled = (True|False)")
set(${examples_enabled} ${CMAKE_MATCH_1})
endif()
# Match tests_enabled flag
if(ns3rc_contents MATCHES "tests_enabled = (True|False)")
set(${tests_enabled} ${CMAKE_MATCH_1})
endif()
# Save variables to parent scope
set(${enabled_modules} "${${enabled_modules}}" PARENT_SCOPE)
set(${examples_enabled} "${${examples_enabled}}" PARENT_SCOPE)
set(${tests_enabled} "${${tests_enabled}}" PARENT_SCOPE)
endif()
endfunction(parse_ns3rc)
endmacro(parse_ns3rc)
function(parse_python_ns3rc ns3rc_contents enabled_modules examples_enabled
tests_enabled ns3rc_location
)
# Save .ns3rc backup
file(WRITE ${ns3rc_location}.backup ${ns3rc_contents})
# Match modules_enabled list
if(ns3rc_contents MATCHES "modules_enabled.*\\[(.*).*\\]")
set(${enabled_modules} ${CMAKE_MATCH_1})
if(${enabled_modules} MATCHES "all_modules")
# If all modules, just clean the filter and all modules will get built by
# default
set(${enabled_modules})
else()
# If modules are listed, remove quotes and replace commas with semicolons
# transforming a string into a cmake list
string(REPLACE "," ";" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "'" "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "\"" "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE " " "" ${enabled_modules} "${${enabled_modules}}")
string(REPLACE "\n" ";" ${enabled_modules} "${${enabled_modules}}")
list(SORT ${enabled_modules})
# Remove possibly empty entry
list(REMOVE_ITEM ${enabled_modules} "")
foreach(element ${${enabled_modules}})
# Inspect each element for comments
if(${element} MATCHES "#.*")
list(REMOVE_ITEM ${enabled_modules} ${element})
endif()
endforeach()
endif()
endif()
string(REPLACE "True" "ON" ns3rc_contents ${ns3rc_contents})
string(REPLACE "False" "OFF" ns3rc_contents ${ns3rc_contents})
# Match examples_enabled flag
if(ns3rc_contents MATCHES "examples_enabled = (ON|OFF)")
set(${examples_enabled} ${CMAKE_MATCH_1})
endif()
# Match tests_enabled flag
if(ns3rc_contents MATCHES "tests_enabled = (ON|OFF)")
set(${tests_enabled} ${CMAKE_MATCH_1})
endif()
# Save variables to parent scope
set(${enabled_modules} "${${enabled_modules}}" PARENT_SCOPE)
set(${examples_enabled} "${${examples_enabled}}" PARENT_SCOPE)
set(${tests_enabled} "${${tests_enabled}}" PARENT_SCOPE)
# Save updated .ns3rc file
message(
${HIGHLIGHTED_STATUS}
"The python-based .ns3rc file format is deprecated and was updated to the CMake format"
)
configure_file(
${PROJECT_SOURCE_DIR}/build-support/.ns3rc-template ${ns3rc_location} @ONLY
)
endfunction(parse_python_ns3rc)
function(log_find_searched_paths)
# Parse arguments
@@ -1866,6 +2022,14 @@ function(find_external_library)
# directories
$ENV{PATH} # Search for libraries in PATH directories
)
# cmake-format: off
#
# Split : separated entries from environment variables
# by replacing separators with ;
#
# cmake-format: on
string(REPLACE ":" ";" library_search_paths "${library_search_paths}")
set(suffixes /build /lib /build/lib / /bin ${path_suffixes})
# For each of the library names in LIBRARY_NAMES or LIBRARY_NAME
@@ -1961,18 +2125,13 @@ function(find_external_library)
list(APPEND parent_dirs ${libdir} ${parent_libdir} ${parent_parent_libdir})
endforeach()
# If we already found a library somewhere, limit the search paths for the
# header
if(parent_dirs)
set(header_search_paths ${parent_dirs})
set(header_skip_system_prefix NO_CMAKE_SYSTEM_PATH)
else()
set(header_search_paths
${search_paths} ${CMAKE_OUTPUT_DIRECTORY} # Search for headers in
# ns-3-dev/build
${CMAKE_INSTALL_PREFIX} # Search for headers in the install
)
endif()
set(header_search_paths
${parent_dirs}
${search_paths}
${CMAKE_OUTPUT_DIRECTORY} # Search for headers in
# ns-3-dev/build
${CMAKE_INSTALL_PREFIX} # Search for headers in the install
)
set(not_found_headers)
set(include_dirs)
@@ -2079,20 +2238,6 @@ function(find_external_library)
endif()
endfunction()
function(write_header_to_modules_map)
if(${ENABLE_SCAN_PYTHON_BINDINGS})
set(header_map ${ns3-headers-to-module-map})
# Trim last comma
string(LENGTH "${header_map}" header_map_len)
math(EXPR header_map_len "${header_map_len}-1")
string(SUBSTRING "${header_map}" 0 ${header_map_len} header_map)
# Then write to header_map.json for consumption of pybindgen
file(WRITE ${PROJECT_BINARY_DIR}/header_map.json "{${header_map}}")
endif()
endfunction()
function(get_target_includes target output)
set(include_directories)
get_target_property(include_dirs ${target} INCLUDE_DIRECTORIES)

View File

@@ -13,4 +13,4 @@ def lp64_to_ilp32(lp64path, ilp32path):
if __name__ == "__main__":
import sys
print(sys.argv)
exit(lp64_to_ilp32(sys.argv[1], sys.argv[2]))
exit(lp64_to_ilp32(sys.argv[1], sys.argv[2]))

View File

@@ -18,20 +18,22 @@
* Authors: Mathew Bielejeski <bielejeski1@llnl.gov>
*/
// clang-format off
#ifndef NS3_VERSION_DEFINES_H_
#define NS3_VERSION_DEFINES_H_
/**
* \file
* \ingroup buildversion
* Defines the macro values for printing the build version.
* These will be populated by the build system.
*/
* \file
* \ingroup buildversion
* Defines the macro values for printing the build version.
* These will be populated by the build system.
*/
/**
* \ingroup buildversion
* @{
*/
* \ingroup buildversion
* @{
*/
/**
* The first tag found which matches the pattern ns-3*.
@@ -66,7 +68,7 @@
*
* Type: integer
*/
#cmakedefine NS3_VERSION_MAJOR @NS3_VERSION_MAJOR@
#define NS3_VERSION_MAJOR @NS3_VERSION_MAJOR@
/**
* The minor version extracted from #NS3_VERSION_TAG
@@ -76,7 +78,7 @@
*
* Type: integer
*/
#cmakedefine NS3_VERSION_MINOR @NS3_VERSION_MINOR@
#define NS3_VERSION_MINOR @NS3_VERSION_MINOR@
/**
* The patch number extracted from #NS3_VERSION_TAG
@@ -89,7 +91,7 @@
*
* Type: integer
*/
#cmakedefine NS3_VERSION_PATCH @NS3_VERSION_PATCH@
#define NS3_VERSION_PATCH @NS3_VERSION_PATCH@
/**
* The portion of the #NS3_VERSION_TAG indicating the version
@@ -110,7 +112,7 @@
*
* Type: integer
*/
#cmakedefine NS3_VERSION_TAG_DISTANCE @NS3_VERSION_TAG_DISTANCE@
#define NS3_VERSION_TAG_DISTANCE @NS3_VERSION_TAG_DISTANCE@
/**
* Hash value which uniquely identifies the commit of the
@@ -143,3 +145,5 @@
/** @} */
#endif
// clang-format on