Skip to content

Commit b194e55

Browse files
committed
Add ns-3 wheel
0 parents  commit b194e55

File tree

5 files changed

+316
-0
lines changed

5 files changed

+316
-0
lines changed

.github/workflows/build.yml

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
jobs:
9+
release:
10+
name: Release
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Create draft release
15+
uses: actions/github-script@0.9.0
16+
with:
17+
github-token: ${{secrets.GITHUB_TOKEN}}
18+
script: |
19+
const fs = require('fs');
20+
21+
const release = await github.repos.createRelease({
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
tag_name: new Date().toISOString().replace(/[T:]/g, '-').split('.')[0],
25+
target_commitish: context.sha,
26+
draft: true,
27+
prerelease: true,
28+
});
29+
30+
fs.mkdirSync('release-info');
31+
fs.writeFileSync('release-info/release.json', JSON.stringify({
32+
id: release.data.id,
33+
upload_url: release.data.upload_url,
34+
}));
35+
36+
- name: Upload release-info
37+
uses: actions/upload-artifact@v1
38+
with:
39+
name: release-info
40+
path: release-info
41+
42+
build:
43+
name: ${{ matrix.wheel }}
44+
runs-on: ubuntu-latest
45+
needs: release
46+
container:
47+
image: debian:10
48+
49+
strategy:
50+
matrix:
51+
wheel:
52+
- ns-3
53+
fail-fast: false
54+
55+
steps:
56+
- name: Checkout code
57+
uses: actions/checkout@v2
58+
59+
- name: Execute ${{ matrix.wheel }}/build.sh
60+
run: exec ${{ matrix.wheel }}/build.sh
61+
62+
- name: Download release-info
63+
uses: actions/download-artifact@v1
64+
with:
65+
name: release-info
66+
67+
- name: Upload ${{ matrix.wheel }}
68+
uses: actions/github-script@0.9.0
69+
with:
70+
github-token: ${{secrets.GITHUB_TOKEN}}
71+
script: |
72+
const fs = require('fs');
73+
74+
const release = JSON.parse(fs.readFileSync('release-info/release.json'), 'utf8');
75+
const path = process.env.ASSET_PATH;
76+
const name = process.env.ASSET_NAME;
77+
const data = fs.readFileSync(path);
78+
79+
await github.repos.uploadReleaseAsset({
80+
url: release.upload_url,
81+
headers: {
82+
'content-type': 'application/zip',
83+
'content-length': data.length,
84+
},
85+
name,
86+
data,
87+
});
88+
89+
publish:
90+
name: Publish
91+
runs-on: ubuntu-latest
92+
needs: build
93+
94+
steps:
95+
- name: Download release-info
96+
uses: actions/download-artifact@v1
97+
with:
98+
name: release-info
99+
100+
- name: Publish release
101+
uses: actions/github-script@0.9.0
102+
with:
103+
github-token: ${{secrets.GITHUB_TOKEN}}
104+
script: |
105+
const fs = require('fs');
106+
107+
const release = JSON.parse(fs.readFileSync('release-info/release.json'), 'utf8');
108+
109+
await github.repos.updateRelease({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
release_id: release.id,
113+
draft: false,
114+
});

ns-3/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import os
2+
3+
__BASE_PATH = os.path.dirname(os.path.abspath(__file__))
4+
5+
def __extend_environ(key, *args):
6+
old_value = os.environ.get(key, '')
7+
if old_value != '':
8+
old_value += os.pathsep
9+
os.environ[key] = old_value + os.path.join(*args)
10+
11+
__extend_environ('PATH', __BASE_PATH, '_', 'bin')

ns-3/build.sh

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/bin/sh -e
2+
3+
section() {
4+
echo "##[section]$@"
5+
}
6+
7+
set_env() {
8+
echo "$1=$2"
9+
echo "::set-env name=$1::$2"
10+
}
11+
12+
command() {
13+
echo "##[command]$@"
14+
"$@"
15+
}
16+
17+
workdir() {
18+
if [ ! -d "$1" ]; then
19+
command mkdir -p "$1"
20+
fi
21+
command cd "$1"
22+
}
23+
24+
run() {
25+
echo "##[group]$@"
26+
local code=0
27+
("$@") || code=$?
28+
echo "##[endgroup]"
29+
return $code
30+
}
31+
32+
runsh() {
33+
echo "##[group]$1"
34+
local code=0
35+
(sh -c "$1") || code=$?
36+
echo "##[endgroup]"
37+
return $code
38+
}
39+
40+
repo="$PWD"
41+
base="$repo/ns-3"
42+
43+
section ---------------- Install ----------------
44+
run apt-get update
45+
run apt-get install -y --no-install-recommends \
46+
bzip2 \
47+
cmake \
48+
curl \
49+
g++ \
50+
git \
51+
libclang-dev \
52+
llvm-dev \
53+
make \
54+
patch \
55+
patchelf \
56+
python3-dev \
57+
python3-pip \
58+
python3-setuptools \
59+
python3-wheel \
60+
qt5-default \
61+
zip \
62+
&& true
63+
64+
65+
run pip3 install \
66+
cxxfilt \
67+
git+https://github.com/felix-gohla/pygccxml@v1.9.2 \
68+
&& true
69+
70+
section ---------------- CastXML ----------------
71+
workdir /opt/castxml
72+
run git clone --branch v0.2.0 --depth 1 https://github.com/CastXML/CastXML.git .
73+
run test "$(git rev-parse HEAD)" = 5ba47e3b67c4a9070e8404ed2db4d16c52e4267b
74+
run cmake .
75+
run make -j $(nproc)
76+
run make install
77+
78+
export NS3_VERSION=3.30
79+
80+
# 3.30
81+
ns3_download_sha1=b4d40bb9777ee644bdba50e3a2e221da85715b4e
82+
83+
section ---------------- download ----------------
84+
workdir /opt/ns-3
85+
run curl -L -o ../ns-3.tar.bz2 https://mgjm.de/ns-allinone-$NS3_VERSION.tar.bz2
86+
runsh "echo '${ns3_download_sha1} ../ns-3.tar.bz2' | sha1sum -c"
87+
run tar xj --strip-components 1 -f ../ns-3.tar.bz2
88+
89+
90+
section ---------------- NetAnim ----------------
91+
run patch -p 1 -i "$base/netanim_python_$NS3_VERSION.patch"
92+
93+
workdir netanim-*
94+
run qmake NetAnim.pro
95+
run make -j $(nproc)
96+
97+
section ---------------- ns-3 ----------------
98+
workdir "/opt/ns-3/ns-$NS3_VERSION"
99+
run ./waf configure
100+
run ./waf --apiscan=netanim && \
101+
102+
workdir "/opt/ns-3"
103+
run ./build.py -- install --destdir=/ns-3-build
104+
run cp netanim-*/NetAnim /ns-3-build/usr/local/bin
105+
106+
section ---------------- python wheel ----------------
107+
run cp "$base/__init__.py" /ns-3-build/usr/local/lib/python3/dist-packages/ns/
108+
run cp -r "$base/ns" /opt/ns
109+
110+
workdir /opt/ns
111+
run python3 setup.py bdist_wheel
112+
run python3 -m wheel unpack -d patch "dist/ns-$NS3_VERSION-py3-none-any.whl"
113+
114+
ns3_patch="patch/ns-$NS3_VERSION"
115+
116+
for f in "$ns3_patch"/ns/*.so; do
117+
run patchelf --set-rpath '$ORIGIN/_/lib' "$f";
118+
done
119+
120+
for f in "$ns3_patch"/ns/_/bin/*; do
121+
run patchelf --set-rpath '$ORIGIN/../lib' "$f";
122+
run chmod +x "$f";
123+
done
124+
125+
run mkdir dist2
126+
run python3 -m wheel pack -d dist2 "$ns3_patch"
127+
128+
asset_name="ns-$NS3_VERSION-py3.whl"
129+
asset_path="$base/$asset_name"
130+
run cp "dist2/ns-$NS3_VERSION-py3-none-any.whl" "$asset_path"
131+
132+
section ---------------- done ----------------
133+
set_env ASSET_PATH "$asset_path"
134+
set_env ASSET_NAME "$asset_name"

ns-3/netanim_python_3.30.patch

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--- a/ns-3.30/src/netanim/wscript 2019-11-28 10:06:08.778243830 +0000
2+
+++ b/ns-3.30/src/netanim/wscript 2019-11-28 10:06:02.410243559 +0000
3+
@@ -16,4 +16,4 @@
4+
headers.source = ['model/animation-interface.h', ]
5+
if (bld.env['ENABLE_EXAMPLES']) :
6+
bld.recurse('examples')
7+
-
8+
+ bld.ns3_python_bindings()

ns-3/ns/setup.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
from sys import platform
5+
from setuptools import setup
6+
from setuptools.command.install import install
7+
from distutils.command.build import build
8+
from subprocess import call
9+
from multiprocessing import cpu_count
10+
11+
NS3_BUILD_PATH = '/ns-3-build'
12+
NS3_VERSION = os.environ['NS3_VERSION']
13+
14+
class NS3Build(build):
15+
def run(self):
16+
super().run()
17+
self.copy_tree(f'{NS3_BUILD_PATH}/usr/local/lib/python3/dist-packages/ns', self.build_lib + '/ns')
18+
self.copy_tree(f'{NS3_BUILD_PATH}/usr/local/lib', self.build_lib + '/ns/_/lib')
19+
self.copy_tree(f'{NS3_BUILD_PATH}/usr/local/bin', self.build_lib + '/ns/_/bin')
20+
21+
class NS3Install(install):
22+
def run(self):
23+
super().run()
24+
self.copy_tree(self.build_lib, self.install_lib)
25+
26+
def read(filename):
27+
with open(filename, 'r') as file:
28+
return file.read()
29+
30+
setup(
31+
name='ns',
32+
version=NS3_VERSION,
33+
description='a discrete-event network simulator for internet systems',
34+
maintainer='Martin Michaelis',
35+
maintainer_email='code@mgjm.de',
36+
license='GPLv2',
37+
url='https://www.nsnam.org',
38+
long_description=read(f'/opt/ns-3/ns-{NS3_VERSION}/README.md'),
39+
long_description_content_type='text/markdown',
40+
classifiers=[
41+
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
42+
'Operating System :: Unix',
43+
'Programming Language :: C++',
44+
],
45+
cmdclass={
46+
'build': NS3Build,
47+
'install': NS3Install,
48+
},
49+
)

0 commit comments

Comments
 (0)