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
- since the unmodified
ns3simulator compiles on the Mac, it is not the ARM platform as such that causes problems ns3compiles a bunch of standalone dynamic libraries- my best guess right now is that the
Ipv4Headerdefinition is part of a different library than thePhyEntityand so it cannot call the constructor - probably
gccallows such undefined symbols in dynamic libraries, which should indeed be fine as long as the final executable links all symbols in, right? - I've tried to configure
clangto allow the same by following this post- i.e. I've set the environment variable
OTHER_LDFLAGSto-undefined dynamic_lookupand recompiled, but to no avail
- i.e. I've set the environment variable
- my best guess right now is that the
I 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
Ipv4Headerthat 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 thesrc/wifi/CMakeLists.txt, underbuild_lib(...)you must addThis 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_64on 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.