import shutil
import sys
import sysconfig
import os
from Cython.Build import cythonize
cmakeCompiler = None
buildDirectory = "build/build_python"
ninja_available = False
enable_osx_crossbuild = False
build_tests = False
if sys.version_info.major < 3:
print("ERROR: NetworKit requires Python 3.")
sys.exit(1)
if "CXX" in os.environ:
cmakeCompiler = os.environ["CXX"]
if "NETWORKIT_OVERRIDE_CXX" in os.environ:
cmakeCompiler = os.environ["NETWORKIT_OVERRIDE_CXX"]
if "NETWORKIT_OSX_CROSSBUILD" in os.environ:
enable_osx_crossbuild = True
if "NETWORKIT_BUILD_TESTS" in os.environ:
build_tests = True
if shutil.which("cmake") is None:
print("ERROR: NetworKit compilation requires cmake.")
sys.exit(1)
ninja_available = shutil.which("ninja") is not None
if not (ninja_available or shutil.which("make")):
print("ERROR: NetworKit compilation requires Make or Ninja.")
sys.exit(1)
try:
from setuptools import setup except ImportError:
print("ERROR: Setuptools is required to install networkit python module.\nInstall via pip3 install setuptools.")
sys.exit(1)
os_soabi = sysconfig.get_config_var('SOABI')
if os_soabi is None:
os_soabi = sysconfig.get_config_var('EXT_SUFFIX').split(".")[1]
import os
import platform
import subprocess
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-j", "--jobs", dest="jobs", help="specify number of jobs")
(options,args) = parser.parse_known_args()
if options.jobs is not None:
jobs = options.jobs
if "NETWORKIT_PARALLEL_JOBS" in os.environ:
jobs = int(os.environ["NETWORKIT_PARALLEL_JOBS"])
else:
import multiprocessing
jobs = multiprocessing.cpu_count()
sys.argv = [__file__] + args
candidates = ["g++", "g++-8", "g++-7", "g++-6.1", "g++-6", "g++-5.5", "g++-5.4", "g++-5.3", "g++-5", "clang++", "clang++-3.9"]
def determineCompiler(candidates, std, flags):
sample = open("sample.cpp", "w")
sample.write("""
#include <omp.h>
#include <iostream>
void helloWorld() {
std::cout << "Hello world" << std::endl;
}
int main (int argc, char *argv[]) {
helloWorld();
int nthreads, tid;
#pragma omp parallel private(nthreads, tid)
{
tid = omp_get_thread_num();
std::cout << \"Hello World from thread = \" << tid << std::endl;
if (tid == 0) {
nthreads = omp_get_num_threads();
std::cout << \"Number of threads = \" << nthreads << std::endl;
}
}
}""")
sample.close()
for compiler in candidates:
cmd = [compiler,"-o","test_build","-std={}".format(std)]
cmd.extend(flags)
cmd.append("sample.cpp")
try:
my_env = os.environ.copy()
if subprocess.call(cmd,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, env=my_env) == 0:
os.remove("sample.cpp")
os.remove("test_build")
return compiler
except:
pass
try:
os.remove("sample.cpp")
except:
pass
return None
if cmakeCompiler is None:
if sys.platform == "darwin":
try:
proc = subprocess.run(['brew','--prefix'], stdout=subprocess.PIPE)
brewPrefix = proc.stdout.decode('utf-8').strip()
cmakeCompiler = determineCompiler(["c++"], "c++17", ["-Xpreprocessor", "-fopenmp", "-I" + str(brewPrefix) + "/include", "-L" + str(brewPrefix) + "/lib", "-lomp"])
except:
pass
if sys.platform == "win32":
cmakeCompiler = "cl"
print("The default for Windows is to use cl.exe (MSVC), be sure to install and activate Visual Studio command line tools.")
if cmakeCompiler is None:
cmakeCompiler = determineCompiler(candidates, "c++17", ["-fopenmp"])
if cmakeCompiler is None:
print("ERROR: No suitable compiler found. Install any of these: ", candidates)
print(" If you have a suitable compiler installed, which is not a standard path, you can override detection by setting 'export NETWORKIT_OVERRIDE_CXX=<compiler-path>'")
if sys.platform == "darwin":
print("If using AppleClang, OpenMP is needed. Use brew or macports to install libomp.")
exit(1)
def buildNetworKit(install_prefix, externalCore=False, externalTlx=None, withTests=False, rpath=None):
try:
os.makedirs(buildDirectory)
except FileExistsError:
pass
abs_prefix = os.path.join(os.getcwd(), install_prefix)
comp_cmd = ["cmake","-DCMAKE_BUILD_TYPE=Release"]
comp_cmd.append("-DCMAKE_INSTALL_PREFIX="+abs_prefix)
comp_cmd.append("-DCMAKE_CXX_COMPILER="+cmakeCompiler)
comp_cmd.append("-DNETWORKIT_FLATINSTALL=ON")
from sysconfig import get_paths, get_config_var
comp_cmd.append("-DNETWORKIT_PYTHON="+get_paths()['include']) comp_cmd.append("-DNETWORKIT_PYTHON_EXECUTABLE="+sys.executable) comp_cmd.append("-DNETWORKIT_PYTHON_SOABI="+os_soabi) if externalCore:
if sys.platform == "win32":
print("Builds with an external core are not supported on Windows.")
exit(1)
comp_cmd.append("-DNETWORKIT_BUILD_CORE=OFF")
if build_tests:
comp_cmd.append("-DNETWORKIT_BUILD_TESTS=ON")
if sys.platform == "win32":
comp_cmd.append("-DNETWORKIT_STATIC=ON") comp_cmd.append("-DNETWORKIT_BUILDING_STATELIB=ON") comp_cmd.append("-DNETWORKIT_PYTHON_VERSION="+sysconfig.get_python_version())
if enable_osx_crossbuild:
comp_cmd.append("-DCMAKE_OSX_ARCHITECTURES='arm64'")
if externalTlx:
comp_cmd.append("-DNETWORKIT_EXT_TLX="+externalTlx)
if ninja_available:
comp_cmd.append("-GNinja")
comp_cmd.append(os.getcwd()) if rpath:
comp_cmd.append("-DNETWORKIT_PYTHON_RPATH="+rpath)
print("initializing NetworKit compilation with: '{0}'".format(" ".join(comp_cmd)), flush=True)
if not subprocess.call(comp_cmd, cwd=buildDirectory) == 0:
print("cmake returned an error, exiting setup.py")
exit(1)
build_cmd = []
if ninja_available:
build_cmd = ["ninja", "install", "-j"+str(jobs)]
else:
build_cmd = ["make", "install", "-j"+str(jobs)]
print("Build with: '{0}'".format(" ".join(build_cmd)), flush=True)
if not subprocess.call(build_cmd, cwd=buildDirectory) == 0:
print("Build tool returned an error, exiting setup.py")
exit(1)
from setuptools import Command
from setuptools import Extension
class build_ext(Command):
sep_by = " (separated by '%s')" % os.pathsep
user_options = [
('inplace', 'i',
"ignore build-lib and put compiled extensions into the source " +
"directory alongside your pure Python modules"),
('include-dirs=', 'I',
"list of directories to search for header files" + sep_by),
('library-dirs=', 'L',
"directories to search for external C libraries" + sep_by),
('networkit-external-core', None,
"use external NetworKit core library"),
('external-tlx=', None,
"absolute path to external tlx library"),
('rpath=', 'r', "additional custom rpath references")
]
def initialize_options(self):
self.build_lib = None self.build_temp = None self.inplace = False
self.include_dirs = None
self.library_dirs = None
self.networkit_external_core = False
self.external_tlx = None
self.rpath = None
self.extensions = None
self.package = None
def finalize_options(self):
self.set_undefined_options('build',
('build_lib', 'build_lib'),
('build_temp', 'build_temp'))
self.extensions = self.distribution.ext_modules
self.package = self.distribution.ext_package
def get_source_files(self):
sources = [ ]
for subdir, dirs, files in os.walk('networkit'):
for filename in files:
sources.append(os.path.join(subdir, filename))
return sources
def get_ext_fullname(self, extname):
if self.package is not None:
return self.package + '.' + extname
return extname
def get_ext_filename(self, fullname):
return fullname + '.' + os_soabi + '.so'
def run(self):
prefix = self.build_lib
if self.inplace:
prefix = self.distribution.src_root or os.getcwd()
buildNetworKit(prefix, externalCore=self.networkit_external_core, externalTlx=self.external_tlx, rpath=self.rpath)
def get_ext_fullpath(self, ext_name):
fullname = self.get_ext_fullname(ext_name)
modpath = fullname.split('.')
filename = self.get_ext_filename(modpath[-1])
if not self.inplace:
filename = os.path.join(*modpath[:-1]+[filename])
return os.path.join(self.build_lib, filename)
package = '.'.join(modpath[0:-1])
build_py = self.get_finalized_command('build_py')
package_dir = os.path.abspath(build_py.get_package_dir(package))
return os.path.join(package_dir, filename)
def get_outputs(self):
outputs = []
for ext in self.extensions:
outputs.append(self.get_ext_fullpath(ext.name))
return outputs
from setuptools import find_packages import version
compiler_directives = {}
if build_tests:
compiler_directives['linetrace'] = True
compiler_directives['language_level'] = 3
setup(
name = version.name,
version = version.version,
author = version.author,
author_email = version.author_email,
url = version.url,
download_url = version.download_url,
description = version.description,
long_description = version.long_description,
license = version.license,
packages = find_packages(),
package_data = {'networkit.profiling': ['html/*','latex/*','description/*']},
keywords = version.keywords,
platforms = version.platforms,
classifiers = version.classifiers,
cmdclass = {'build_ext': build_ext},
ext_modules = cythonize(["networkit/*pyx"], compiler_directives=compiler_directives),
test_suite = 'nose.collector',
install_requires = version.install_requires,
zip_safe = False)
try:
import tkinter del tkinter except:
print("WARNING: _tkinter is necessary for networkit.profiling module if not used via jupyter.\nInstall tkinter if needed")