I've downloaded ns-3.39
, unpacked and compiled it using
wget https://www.nsnam.org/releases/ns-allinone-3.39.tar.bz2
tar xfj ns-allinone-3.39.tar.bz2
cd ns-allinone-3.39/ns-3.39/
./ns3 configure --disable-examples --disable-tests -d default
./ns3 build
this works fine.
When I add an #include "ns3/ipv4-header.h"
to ns-3.39/src/wifi/model/phy-entity.cc
and try to use the Ipv4Header
class from that header by instantiating an Ipv4Header ipHeader;
inside phy-entity.cc:528
in its DropPreambleEvent
function, I get the following compilation error:
ld: Undefined symbols:
ns3::Ipv4Header::Ipv4Header(), referenced from:
ns3::PhyEntity::DropPreambleEvent(ns3::Ptr<ns3::WifiPpdu const>, ns3::WifiPhyRxfailureReason, ns3::Time) in phy-entity.cc.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am compiling on a MacBook M2 Pro with clang
targeted for ARM. When I do the exact same thing on a x86_64 Linux server with gcc
, it works.
I would really like to get this working so that I can work locally. I've sunk some time into this, and found the following
ns3
simulator compiles on the Mac, it is not the ARM platform as such that causes problemsns3
compiles a bunch of standalone dynamic libraries
Ipv4Header
definition is part of a different library than the PhyEntity
and so it cannot call the constructorgcc
allows such undefined symbols in dynamic libraries, which should indeed be fine as long as the final executable links all symbols in, right?clang
to allow the same by following this post
OTHER_LDFLAGS
to -undefined dynamic_lookup
and recompiled, but to no availI am out of ideas. What could I try?
I've got it running. For those that come after me that have similar troubles:
I've learned that the ns3 core is structured module-wise (forgive me if you know this already, I am learning as I go), so there is no direct link between the wifi module and the internet module. Modules are compiled into dynamic libraries, so that you can pick and choose what you need. Makes total sense to me from a software architecture standpoint.
In my project we've been changing the wifi module code (as stated in the original post), by including stuff such as the Ipv4Header
that comes from the internet module.
To make this work when compiling with clang/arm
, you need to explicitly link the internet library with the wifi library by adding 1 line to the src/wifi/CMakeLists.txt
, under build_lib(...)
you must add
build_lib(
LIBNAME wifi
...
LIBRARIES_TO_LINK
...
${libinternet}
...
)
This might be bad coding style as we break the isolation between the libraries; we'll accept it for the task at hand.
What I still don't understand is why gcc/x86_64
on a Linux system DOES NOT REQUIRE THIS. Somehow it determines to link in this library on its own? If anyone could explain to me how/why this works, I'd love to hear it.