Additional (external) contrib folder need

69 views
Skip to first unread message

sami.r...@magister.fi

unread,
Aug 8, 2024, 8:51:59 AM8/8/24
to ns-developers
Hi all,

I'm working as senior manager at Magister Solutions participating also development of our ns-3 based simulators. We have lately changed our code structure so that ns-3 is used as git submodule.

This expects that we need to link our several modules including main simulator module to contrib folder of ns-3, because we do not want to modify ns-3 itself (even we have copy of it in our own private repo) and simulators might use different version of the ns-3.

Could you consider a way to include external folder(s) to be used as contrib folder in addition to ns-3/contrib folder? This would remove need to link external folder(s) to contrib folder inside ns-3. Linking works also, but we would appreciate some more sophisticated way supported by ns-3 platform. 

Best regards,
-sami-

Sami Rantanen
Senior Manager, Simulation Services
Magister Solutions Ltd.

Gabriel Ferreira

unread,
Aug 8, 2024, 9:28:05 AM8/8/24
to ns-developers
If you are not changing upstream ns-3, you can already import it as a CMake subproject and link against its targets.
You can define your project like the following

       top level (dependent on ns-3 and non ns-3. e.g. ns3::libcore, ns3::libspectrum, libtorch, etc)
       |             |
ns-3      non ns-3 dependencies (e.g. libtorch)

We maybe could support that, but I don't remember if CMake does support upper directories via add_subdirectory calls.
And the biggest problem is that both contrib and src directories are scanned automatically for modules.
I don't think it is reasonable to scan directories on the same level as ns-3-dev for modules, so you would indeed need to change ns-3 in some way.

sami.r...@magister.fi

unread,
Aug 8, 2024, 11:44:24 PM8/8/24
to ns-developers
Hi,

Thanks for the answers. Yes, mostly like some changes needs to be done to ns-3, but in our case same ns-3 repo is used by several simulators and we do not want to copy it but use same ns-3 repo for all.
Actually my idea was that if it can be configured a custom folder (outside of the ns-3) to scan automatically in addition to contrib and src directories scanned already.

Kind regards,
-sami-

sami.r...@magister.fi

unread,
Nov 28, 2024, 7:44:23 AM11/28/24
to ns-developers
Dear all,

This is not showstopper,  but have you considered this?

Kinds regards,
-sami-

Gabriel Ferreira

unread,
Nov 28, 2024, 8:58:31 AM11/28/24
to ns-developers
Hi Sami,

Thought it would be a lot of trouble (if even possible), but it is actually doable and not that hard. Not properly tested.

```
Index: build-support/custom-modules/ns3-executables.cmake
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/build-support/custom-modules/ns3-executables.cmake b/build-support/custom-modules/ns3-executables.cmake
--- a/build-support/custom-modules/ns3-executables.cmake (revision f6ffa1e0fddad897d4c82b4cc999e2c6262768ce)
+++ b/build-support/custom-modules/ns3-executables.cmake (date 1732801860137)
@@ -137,6 +137,11 @@
     )
   endif()
 
+  # Handle ns-3-external-contrib/module (which will have output binaries mapped to contrib/module)
+  if (${BEXEC_EXECUTABLE_DIRECTORY_PATH} MATCHES "ns-3-external-contrib")
+    string(REGEX REPLACE ".*ns-3-external-contrib" "${PROJECT_SOURCE_DIR}/contrib" BEXEC_EXECUTABLE_DIRECTORY_PATH "${BEXEC_EXECUTABLE_DIRECTORY_PATH}")
+  endif()
+
   set_runtime_outputdirectory(
     "${BEXEC_EXECNAME}" "${BEXEC_EXECUTABLE_DIRECTORY_PATH}/"
     "${BEXEC_EXECNAME_PREFIX}"
Index: CMakeLists.txt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt (revision f6ffa1e0fddad897d4c82b4cc999e2c6262768ce)
+++ b/CMakeLists.txt (date 1732801335237)
@@ -121,6 +121,12 @@
 # Scan contribution libraries
 subdirlist(contrib_libs_to_build ${CMAKE_CURRENT_SOURCE_DIR}/contrib)
 
+# Scan for additional contribution libraries OUTSIDE the ns-3 source directory, in the ns-3-external-contrib directory
+if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../ns-3-external-contrib)
+  subdirlist(external_contrib_libs_to_build ${CMAKE_CURRENT_SOURCE_DIR}/../ns-3-external-contrib)
+  set(contrib_libs_to_build ${contrib_libs_to_build} ${external_contrib_libs_to_build})
+endif()
+
 # Before filtering, we need to load settings from .ns3rc
 parse_ns3rc(
   ns3rc_enabled_modules ns3rc_disabled_modules ns3rc_examples_enabled
Index: build-support/custom-modules/ns3-module-macros.cmake
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/build-support/custom-modules/ns3-module-macros.cmake b/build-support/custom-modules/ns3-module-macros.cmake
--- a/build-support/custom-modules/ns3-module-macros.cmake (revision f6ffa1e0fddad897d4c82b4cc999e2c6262768ce)
+++ b/build-support/custom-modules/ns3-module-macros.cmake (date 1732801860137)
@@ -356,10 +356,11 @@
   set(multiValueArgs SOURCE_FILES HEADER_FILES LIBRARIES_TO_LINK)
   cmake_parse_arguments("BLIB_EXAMPLE" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
+  # cmake-format: on
+
   # Get path src/module or contrib/module
   string(REPLACE "${PROJECT_SOURCE_DIR}/" "" FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
 
-  # cmake-format: on
   check_for_missing_libraries(
     missing_dependencies "${BLIB_EXAMPLE_LIBRARIES_TO_LINK}"
   )
Index: build-support/custom-modules/ns3-contributions.cmake
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/build-support/custom-modules/ns3-contributions.cmake b/build-support/custom-modules/ns3-contributions.cmake
--- a/build-support/custom-modules/ns3-contributions.cmake (revision f6ffa1e0fddad897d4c82b4cc999e2c6262768ce)
+++ b/build-support/custom-modules/ns3-contributions.cmake (date 1732800285178)
@@ -15,9 +15,13 @@
   # Add contribution folders to be built
   foreach(contribname ${contribution_list})
     set(folder "contrib/${contribname}")
+    set(external_folder "../ns-3-external-contrib/${contribname}")
     if(EXISTS ${PROJECT_SOURCE_DIR}/${folder}/CMakeLists.txt)
       message(STATUS "Processing ${folder}")
       add_subdirectory(${folder})
+    elseif(EXISTS ${PROJECT_SOURCE_DIR}/${external_folder}/CMakeLists.txt)
+      message(STATUS "Processing ${external_folder}")
+      add_subdirectory(${external_folder} ${PROJECT_BINARY_DIR}/contrib/${contribname})
     else()
       message(${HIGHLIGHTED_STATUS}
               "Skipping ${folder} : it does not contain a CMakeLists.txt file"

```

sami.r...@magister.fi

unread,
Nov 28, 2024, 9:32:11 AM11/28/24
to ns-developers
Hi Gabriel,

I didn't fully understood if this will be included or not in future in ns-3 make files.
But I would replace the 'ns-3-external-contrib' with information from variable so that folder name is not hardcoded as in your code snipple.

br,
-sami-


Gabriel Ferreira

unread,
Nov 28, 2024, 10:06:17 AM11/28/24
to ns-developers
It can be included. Needs testing first.
If it is merged, I plan to make it hardcoded on purpose.
It just saves maintainers time by preventing people from using a crazy corner case path that breaks things somehow, and then complain it doesn't work.

sami.r...@magister.fi

unread,
Nov 28, 2024, 11:11:50 AM11/28/24
to ns-developers
Hi Gabriel,

Actually hardcoded folder is okay, no problem.
Very good that will be coming-

Thanks,

-sami-

Gabriel Ferreira

unread,
Nov 28, 2024, 4:43:18 PM11/28/24
to ns-developers

pd...@mac.com

unread,
Nov 28, 2024, 4:47:12 PM11/28/24
to sami.r...@magister.fi, ns-developers
Suggest a (hard-coded) environment variable might be preferable to a fixed relative path. This would enable a lot of flexibility on the user’s side, yet still be specific on the ns-3 side. 

Peter
------------------

On Nov 28, 2024, at 6:12 AM, sami.r...@magister.fi <sami.r...@magister.fi> wrote:

Hi Gabriel,
--
You received this message because you are subscribed to the Google Groups "ns-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-developer...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/ns-developers/8159b91a-435f-4878-ab3e-76e912d63cf7n%40googlegroups.com.

Gabriel Ferreira

unread,
Nov 29, 2024, 5:18:28 AM11/29/24
to ns-developers
Peter, you mean like checking an environment variable, and if it's not set, assume the default value?

I think it falls into the same problem as a configurable path. It is flexible, yes.
Do you want to give this flexibility? I certainly don't, because I'm absolutely sure someone will break it and then complain.
It is like Ford said:  any customer can have a car painted any color that he wants, so long as it is black. 😅

pd...@mac.com

unread,
Nov 29, 2024, 11:03:50 AM11/29/24
to Gabriel Ferreira, ns-developers
If it’s not set perhaps do nothing. 

IMO it would be much more useful if there was some flexibility. We can’t possibly anticipate all possible environments and uses, so we shouldn’t be too rigid. 

In Sami’s case it sounds like this external directory can be in the parent directory alongside ns-3, but that might not be natural in other cases. For example on our clusters it’s common to install shared toolkits in directories like 
/usr/gapps/ns-3

Obviously we can’t just dump project-specific code in the shared /usr/gapps. On our clusters the natural place for that would be somewhere below the user’s home directory, or below a project directory. So a single hard-coded relative path wouldn’t work for us. 

An environment variable would also enable several projects to use the same base ns-3 install. This would be very helpful to us, and save either re-adding our customizations on top of each name-3 release, or porting things between projects. 

Going further, an environment variable would enable a simpler teaching install. The Instructor sets up the ns-3 directory, possibly including customizations. Each student then just has to set the environment variable (and build directory). This means the students don’t have to download ns-3, they can’t mess up the base system, and it saves some disk space. 

Peter
------------------

On Nov 29, 2024, at 12:19 AM, Gabriel Ferreira <gabriel...@gmail.com> wrote:

Peter, you mean like checking an environment variable, and if it's not set, assume the default value?

Sami Rantanen

unread,
Nov 29, 2024, 12:41:33 PM11/29/24
to pd...@mac.com, Gabriel Ferreira, ns-developers
Hi all,

Actually our need would be to have two external contrib folders in some cases. So e.g. env variable would be nice to have for this defining list of the external folders. But I see also point/risks in this approach.

-sami-

Gabriel Ferreira

unread,
Nov 29, 2024, 12:47:34 PM11/29/24
to ns-developers

> IMO it would be much more useful if there was some flexibility.

Agreed.


> We can’t possibly anticipate all possible environments and uses, so we shouldn’t be too rigid. 

This is where I diverge. We can't anticipate, we can't test, people complain about things breaking.


> For example on our clusters it’s common to install shared toolkits in directories like /usr/gapps/ns-3

In all clusters I've used so far, we don't actually get to write to these shared directories, only home directory.
If ns-3 is there, in a read-only directory, this is going to be useless, no?
Unless you also move the build directory outside of ns-3, but the lock-file still is bound to ns-3, so won't work anyways.


> An environment variable would also enable several projects to use the same base ns-3 install.

Dump everything into external-contrib, filter what you want with NS3_ENABLED_MODULES/--enable-modules/.ns3rc.


> Going further, an environment variable would enable a simpler teaching install. The Instructor sets up the ns-3 directory, possibly including customizations. Each student then just has to set the environment variable (and build directory). This means the students don’t have to download ns-3, they can’t mess up the base system, and it saves some disk space.

pip install ns3

It doesn't get easier than that, and it is what I used to teach.
What is still missing is supporting extra modules e.g. nr. I still need to work on that.

On C++ side, the default install is totally sane, so only edge case scenarios actually need to change something.
And I'd expect most CMake users to know how to set the install prefix.
The only custom thing we do here with CMake is the binary directory does not contain the built targets. I hate having them all together. Very confusing and a bazillion intermediate files. =x

Gabriel Ferreira

unread,
Nov 29, 2024, 12:48:55 PM11/29/24
to ns-developers
> Actually our need would be to have two external contrib folders in some cases. So e.g. env variable would be nice to have for this defining list of the external folders. But I see also point/risks in this approach.

Dump everything into external-contrib, filter what you want with NS3_ENABLED_MODULES/--enable-modules/.ns3rc.

Should not be a problem, unless you have different versions of the same modules in the same directory.

pd...@mac.com

unread,
Nov 29, 2024, 2:24:36 PM11/29/24
to Gabriel Ferreira, ns-developers

> On Nov 29, 2024, at 7:47 AM, Gabriel Ferreira <gabriel...@gmail.com> wrote:
>
> > For example on our clusters it’s common to install shared toolkits in directories like /usr/gapps/ns-3
>
> In all clusters I've used so far, we don't actually get to write to these shared directories, only home directory.
> If ns-3 is there, in a read-only directory, this is going to be useless, no?
> Unless you also move the build directory outside of ns-3, but the lock-file still is bound to ns-3, so won't work anyways.

We can ask for a shared directory on our clusters, to facilitate using tool libraries across many projects.

Exactly, set the build directory to some place convenient, and writable. Shouldn’t the lock file be specific to the build directory? Not the main tree?

> > An environment variable would also enable several projects to use the same base ns-3 install.
>
> Dump everything into external-contrib, filter what you want with NS3_ENABLED_MODULES/--enable-modules/.ns3rc.

Three problems with that: it’s one more place for users to screw up, which you‘re anxious to avoid. It doesn’t work if different projects need different versions of the same module, as you said. And if you have many projects it forces you to co-mingle the code, which might not be allowed by policy.

I’m wondering about Sami’s original use case again. It sounds like Sami wants to use the existing ns-3 build system but include an external directory.

First, could he just add a symbolic link in ns-3/contrib pointing to his external directory? Or do we not follow links in contrib?

Second, I think a more typical pattern would be to treat ns-3 as a callable library, and set up a project build system external to ns-3. Perhaps we would be better off providing a write up and stub CMake file showing how to do that, rather than inverting things to have an external project use the ns-3 build system to build itself.

Peter

Gabriel Ferreira

unread,
Nov 29, 2024, 4:05:29 PM11/29/24
to ns-developers
> Shouldn’t the lock file be specific to the build directory? Not the main tree?

It was not like that with waf, and I just reproduced the behavior.

> First, could he just add a symbolic link in ns-3/contrib pointing to his external directory? Or do we not follow links in contrib?

Never tried, but would expect it to work.


> Second, I think a more typical pattern would be to treat ns-3 as a callable library, and set up a project build system external to ns-3. Perhaps we would be better off providing a write up and stub CMake file showing how to do that, rather than inverting things to have an external project use the ns-3 build system to build itself.

Already supported via pkgconfig and cmake import package (as tested by https://gitlab.com/nsnam/ns-3-dev/-/blob/master/utils/tests/test-ns3.py?ref_type=heads#L2262).

cmake_minimum_required(VERSION 3.12..3.12)
project(ns3_consumer CXX)
set(CMAKE_CXX_STANDARD 20)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(test main.cpp)
list(APPEND CMAKE_PREFIX_PATH ./)
include(FindPkgConfig)

pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core-3.42)

target_link_libraries(test PUBLIC PkgConfig::ns3)

OR

cmake_minimum_required(VERSION 3.12..3.12)
project(ns3_consumer CXX)
set(CMAKE_CXX_STANDARD 20)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(test main.cpp)
list(APPEND CMAKE_PREFIX_PATH ./ns-3-install/lib/cmake/ns3)
find_package(ns3 3.42 COMPONENTS core)
target_link_libraries(test PRIVATE ns3::core)

Plus as a cmake subproject (just create a new cmake project, and add ns-3-dev as a subdirectory).

cmake_minimum_required(VERSION 3.12..3.12)
project(ns3_consumer CXX)
set(CMAKE_CXX_STANDARD 20)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(test main.cpp)

add_subdirectory(ns-3-dev)
target_link_libraries(test PRIVATE ns3::core)

Problem is, it won't work with pre-existing modules. But I think this is actually a desired outcome. Depend less on custom ns-3 stuff and treat it like a normal C++ project.
I could write replacement macros to make this magically work, but it is a waste of my time, since I have absolutely 0 use for that.

Sami Rantanen

unread,
Nov 30, 2024, 12:16:47 AM11/30/24
to Gabriel Ferreira, ns-developers
Hi,

Yes we are using symbolic links currently. But we would prefer to use the way I asked here originally. The reason is that in our case ns-3 is used as git submodule in order to use benefits of submodules and without need to touch ns-3 itself.

So our aporoach is to use same ns-3 repo by all simulators and they can decide per simulator which version of ns-3 to use. Ideally we could use nsnam repo directly, currently we have copy of it.


-sami-

--
You received this message because you are subscribed to the Google Groups "ns-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-developer...@googlegroups.com.

Tom Henderson

unread,
Nov 30, 2024, 11:50:20 AM11/30/24
to ns-dev...@googlegroups.com
I'm jumping in late to this thread, but have some comments inline below

On 11/29/24 21:16, Sami Rantanen wrote:
> Hi,
>
> Yes we are using symbolic links currently. But we would prefer to use
> the way I asked here originally. The reason is that in our case ns-3
> is used as git submodule in order to use benefits of submodules and
> without need to touch ns-3 itself.

Historically, the bake build tool was intended for use cases such as
this, although the main use ended up being as the build system for DCE. 
The design is that bake builds all shared library dependencies first and
installs them to a build directory, and then builds ns-3 and installs to
the build directory, along with pkg-config files.  Bake can also fetch
and include contrib modules.  Then, whatever is downstream of ns-3 can
be linked by setting LD_LIBRARY_PATH and PATH to find libraries.  It was
envisioned that if a user had some kind of a program to be built outside
of the ns-3 tree, they would write whatever Makefile was needed and use
the above environment variables.

>
> So our aporoach is to use same ns-3 repo by all simulators and they
> can decide per simulator which version of ns-3 to use. Ideally we
> could use nsnam repo directly, currently we have copy of it.
>
In bake, this is allowed by specifying which version of ns-3 and which
versions of contrib modules.  This is all expressed in the bakefile.conf.

./bake.py configure -e ns-3.41 -e some-ns3-contrib-module-version -e
some-other-contrib-module-version

./bake.py download

./bake.py build

So it seems to me that something like what you want could be maintained
via bake if you wanted to manage it that way instead of with git submodules.

- Tom

Sami Rantanen

unread,
Dec 1, 2024, 8:46:36 AM12/1/24
to Tom Henderson, ns-dev...@googlegroups.com
Hi,

The point is that we want to use git submodules. And maybe I mislead or forgot to mention that modules in external contrib are our custom ns-3 modules. So need is to maintain with git having ns-3 as submodule in order to use same ns-3 repo cross the several simulators. But support I’m asking is not mandatory for us and we can keep using symbolic links. But if somebody else has similar needs then it might worth of considering this.

-sami-

--
You received this message because you are subscribed to the Google Groups "ns-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ns-developer...@googlegroups.com.

Tom Henderson

unread,
Dec 1, 2024, 10:24:46 AM12/1/24
to Sami Rantanen, ns-dev...@googlegroups.com
On 12/1/24 05:46, Sami Rantanen wrote:
> Hi,
>
> The point is that we want to use git submodules.

Understood; I just wanted to point out the project history regarding how
to handle similar cases.

I would be fine with some extension along the lines of !2260 if it meets
your needs. I tend to agree with Peter's views expressed on this
thread, but since Gabriel has to support it, if he just wants to merge
!2260 and be done with it, or adopt some subset of Peter's suggestions,
either would be fine with me.

- Tom
Reply all
Reply to author
Forward
0 new messages