Merge tag 'ns-3.37' into unison

ns-3.37 release
This commit is contained in:
F5
2023-11-11 21:44:45 +08:00
2759 changed files with 6938 additions and 6638 deletions

93
ns3
View File

@@ -30,7 +30,7 @@ def exit_handler(dry_run):
return
if print_buffer == "":
return
print_buffer = print_buffer.replace('\\','/').replace('//','/').replace('/', os.sep)
print_buffer = print_buffer.replace('\\', '/').replace('//', '/').replace('/', os.sep)
if dry_run:
print("The following commands would be executed:")
elif run_verbose:
@@ -110,7 +110,7 @@ def parse_args(argv):
parser_configure.add_argument('-d', '--build-profile',
help='Build profile',
dest='build_profile',
choices=["debug", "default", "release", "optimized"],
choices=["debug", "default", "release", "optimized", "minsizerel"],
action="store", type=str, default=None)
parser_configure.add_argument('-G',
@@ -246,6 +246,15 @@ def parse_args(argv):
parser_run.add_argument('-g', '--valgrind',
help='Change the default command template to run programs with valgrind',
action="store_true", default=None)
parser_run.add_argument('--memray',
help='Use Memray memory profiler for Python scripts. Output will be saved to memray.output',
action="store_true", default=None)
parser_run.add_argument('--heaptrack',
help='Use Heaptrack memory profiler for C++',
action="store_true", default=None)
parser_run.add_argument('--perf',
help='Use Linux\'s perf to profile a program',
action="store_true", default=None)
parser_run.add_argument('--vis', '--visualize',
help='Modify --run arguments to enable the visualizer',
action="store_true", dest="visualize", default=None)
@@ -411,8 +420,10 @@ def print_and_buffer(message):
def clean_cmake_artifacts(dry_run=False):
print_and_buffer("rm -R %s" % os.path.relpath(out_dir, ns3_path))
if not dry_run:
if out_dir == ns3_path:
raise Exception("The output directory and the ns-3 directory are the same. "
"Deleting it can cause data loss.")
shutil.rmtree(out_dir, ignore_errors=True)
cmake_cache_files = glob.glob("%s/**/CMakeCache.txt" % ns3_path, recursive=True)
@@ -420,6 +431,9 @@ def clean_cmake_artifacts(dry_run=False):
dirname = os.path.dirname(cmake_cache_file)
print_and_buffer("rm -R %s" % os.path.relpath(dirname, ns3_path))
if not dry_run:
if dirname == ns3_path:
raise Exception("The CMake cache directory and the ns-3 directory are the same. "
"Deleting it can cause data loss.")
shutil.rmtree(dirname, ignore_errors=True)
if os.path.exists(lock_file):
@@ -539,18 +553,21 @@ def configure_cmake(cmake, args, current_cmake_cache_folder, current_cmake_gener
# Build type
if args.build_profile is not None:
args.build_profile = args.build_profile.lower()
if args.build_profile not in ["debug", "default", "release", "optimized"]:
if args.build_profile not in ["debug", "default", "release", "optimized", "minsizerel", "relwithdebinfo"]:
raise Exception("Unknown build type")
else:
if args.build_profile == "debug":
cmake_args.extend(
"-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON".split())
elif args.build_profile == "default":
elif args.build_profile in ["default", "relwithdebinfo"]:
cmake_args.extend(
"-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF".split())
elif args.build_profile in ["release", "optimized"]:
cmake_args.extend(
"-DCMAKE_BUILD_TYPE=release -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF".split())
else:
cmake_args.extend(
"-DCMAKE_BUILD_TYPE=release -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF".split()
"-DCMAKE_BUILD_TYPE=minsizerel -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF".split()
)
cmake_args.append("-DNS3_NATIVE_OPTIMIZATIONS=%s" % on_off((args.build_profile == "optimized")))
@@ -652,7 +669,7 @@ def update_scratches_list(current_cmake_cache_folder):
def refresh_cmake(current_cmake_cache_folder, output):
ret = subprocess.run([shutil.which("cmake"), ".."], cwd=current_cmake_cache_folder, stdout=output)
ret = subprocess.run([check_program_installed("cmake"), ".."], cwd=current_cmake_cache_folder, stdout=output)
if ret.returncode != 0:
exit(ret.returncode)
update_scratches_list(current_cmake_cache_folder)
@@ -708,17 +725,16 @@ def get_program_shortcuts(build_profile, ns3_version):
# Add an additional shortcut with .exe suffix when running on Windows
if sys.platform == "win32":
ns3_program_map[shortcut_path.replace("\\","/")] = [program]
ns3_program_map[shortcut_path+".exe"] = [program]
ns3_program_map[shortcut_path.replace("\\","/")+".exe"] = [program]
ns3_program_map[shortcut_path.replace("\\", "/")] = [program]
ns3_program_map[shortcut_path + ".exe"] = [program]
ns3_program_map[shortcut_path.replace("\\", "/") + ".exe"] = [program]
if source_shortcut:
cc_shortcut_path = shortcut_path + ".cc"
ns3_program_map[cc_shortcut_path] = [program]
if sys.platform == "win32":
ns3_program_map[cc_shortcut_path] = [program]
ns3_program_map[cc_shortcut_path.replace("\\","/")] = [program]
ns3_program_map[cc_shortcut_path.replace("\\", "/")] = [program]
# Store longest shortcut path for collisions
if cc_shortcut_path not in longest_shortcut_map:
@@ -953,6 +969,7 @@ def build_step(args,
non_executable_targets = ["assemble-introspected-command-line",
"check-version",
"cmake-format",
"coverage_gcc",
"docs",
"doxygen",
"doxygen-no-build",
@@ -1003,6 +1020,23 @@ def build_step(args,
)
def check_program_installed(program_name: str) -> str:
program_path = shutil.which(program_name)
if program_path is None:
print("Executable '{program}' was not found".format(program=program_name.capitalize()))
exit(-1)
return program_path
def check_module_installed(module_name: str):
import importlib
try:
importlib.import_module(module_name)
except ImportError:
print("Python module '{module}' was not found".format(module=module_name))
exit(-1)
def run_step(args, target_to_run, target_args):
libdir = "%s/lib" % out_dir
@@ -1033,24 +1067,42 @@ def run_step(args, target_to_run, target_args):
target_args = [target_to_run] + target_args
target_to_run = "python3"
# running with memray?
if args.memray:
check_module_installed("memray")
target_args = ["-m", "memray", "run", "-o", "memray.output", "--native"] + target_args
# running from ns-3-dev (ns3_path) or cwd
if args.cwd:
working_dir = args.cwd
# running with heaptrack?
if args.heaptrack:
debugging_software.append(check_program_installed("heaptrack"))
# running valgrind?
if args.valgrind:
debugging_software.extend([shutil.which("valgrind"), "--leak-check=full", "--show-leak-kinds=all"])
debugging_software.extend(
[check_program_installed("valgrind"), "--leak-check=full", "--show-leak-kinds=all"])
# running gdb?
if args.gdb:
gdb_eval_command = []
if os.getenv("gdb_eval"):
gdb_eval_command.append("--eval-command=quit")
debugging_software.extend([shutil.which("gdb"), *gdb_eval_command, "--args"])
debugging_software.extend([check_program_installed("gdb"), *gdb_eval_command, "--args"])
# running lldb?
if args.lldb:
debugging_software.extend([shutil.which("lldb"), "--"])
debugging_software.extend([check_program_installed("lldb"), "--"])
# running with perf?
if args.perf:
debugging_software.extend([
check_program_installed("perf"),
"record", "--call-graph", "dwarf", "-a", "-e",
"cache-misses,branch-misses,cpu-cycles,stalled-cycles-frontend,stalled-cycles-backend,context-switches"
])
# running with the visualizer?
if args.visualize:
@@ -1059,6 +1111,7 @@ def run_step(args, target_to_run, target_args):
# running with command template?
if args.command_template:
commands = (args.command_template % target_to_run).split()
check_program_installed(commands[0])
target_to_run = commands[0]
target_args = commands[1:] + target_args
@@ -1086,10 +1139,10 @@ def run_step(args, target_to_run, target_args):
try:
subprocess.run(program_arguments, env=proc_env, cwd=working_dir, shell=use_shell, check=True)
except subprocess.CalledProcessError as e:
# Replace full path to binary to relative path
e.cmd[0] = os.path.relpath(target_to_run, ns3_path)
# Replace list of arguments with a single string
e.cmd = " ".join(e.cmd)
# Replace full path to binary to relative path
e.cmd = e.cmd.replace(os.path.abspath(target_to_run), os.path.relpath(target_to_run, ns3_path))
# Print error message and forward the return code
print(e)
exit(e.returncode)
@@ -1117,7 +1170,7 @@ def non_ambiguous_program_target_list(programs: dict) -> list:
def print_targets_list(ns3_modules: list, ns3_programs: dict) -> None:
def list_to_table(l: list) -> str:
def list_to_table(targets_list: list) -> str:
# Set column width and check how much is space is left at the end
columnwidth = 30
try:
@@ -1127,10 +1180,10 @@ def print_targets_list(ns3_modules: list, ns3_programs: dict) -> None:
dead_space = terminal_width % columnwidth
# Filter the targets with names longer than the column width
large_items = list(filter(lambda x: len(x) >= columnwidth, l))
large_items = list(filter(lambda x: len(x) >= columnwidth, targets_list))
# Then filter the targets with names shorter than the column width
small_items = sorted(list(set(l) - set(large_items)))
small_items = sorted(list(set(targets_list) - set(large_items)))
prev_new_line = 0
output = "\n"