text: #!/usr/bin/python3
  
  import shutil
  import sys
  import sysconfig
  import os
  
  cmakeCompiler = None
  buildDirectory = "build/build_python"
  ninja_available = 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 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 # to ensure setuptools is installed
  except ImportError:
  	print("ERROR: Setuptools is required to install networkit python module.\nInstall via pip3 install setuptools.")
  	sys.exit(1)
  
  import os
  import subprocess #calling cmake, make and cython
  
  ################################################
  # get the optional arguments for the compilation
  ################################################
  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()
  # make sure sys.argv is correct for setuptools
  sys.argv = [__file__] + args
  
  ################################################
  # compiler identification
  ################################################
  
  candidates = ["g++", "g++-8", "g++-7", "g++-6.1", "g++-6", "g++-5.3", "g++-5.2", "g++-5.1", "g++-5", "g++-4.9", "g++-4.8", "clang++", "clang++-3.8", "clang++-3.7"]
  
  def determineCompiler(candidates, std, flags):
  	#TODO: proper c++11 test?
  	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:
  			if subprocess.call(cmd,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,shell=True) == 0:
  				os.remove("sample.cpp")
  				os.remove("test_build.exe")
  				
  				return compiler
  	
  		except:
  			pass
  	try:
  		os.remove("sample.cpp")
  	except:
  		pass
  	return None
  
  # only check for a compiler if none is specified
  if cmakeCompiler is None:
  	cmakeCompiler = determineCompiler(candidates, "c++11", ["-fopenmp"])
  	if cmakeCompiler is None and sys.platform == "darwin":
  		cmakeCompiler = determineCompiler(["c++"], "c++11", ["-Xpreprocessor", "-fopenmp", "-lomp"])
  	if cmakeCompiler is None:
  		print("ERROR: No suitable compiler found. Install any of these: ", candidates)
  		if sys.platform == "darwin":
  			print("If using AppleClang, OpenMP might be needed. Install with: 'brew install libomp'")
  		exit(1)
  
  ################################################
  # functions for cythonizing and building networkit
  ################################################
  
  def cythonizeFile(filepath):
  	cpp_file = filepath.replace("pyx","cpp")
  
  	cython_available = shutil.which("cython") is not None
  	if not cython_available:
  		if not os.path.isfile(cpp_file):
  			print("ERROR: Neither cython nor _NetworKit.cpp is provided. Build cancelled", flush=True)
  			exit(1)
  
  		else:
  			print("Cython not available, but _NetworKit.cpp provided. Continue build without cythonizing", flush=True)
  
  	elif os.path.isfile(cpp_file) and os.path.getmtime(filepath) < os.path.getmtime(cpp_file):
  		print("Cython available; skip as _NetworKit.cpp was create after last modification of _NetworKit.pyx", flush=True)
  
  	else:
  		print("Cythonizing _NetworKit.pyx...", flush=True)
  		if not os.path.isfile(filepath):
  			print("_NetworKit.pyx is not available. Build cancelled.")
  			exit(1)
  		comp_cmd = ["cython","-3","--cplus","-t",filepath]
  		if not subprocess.call(comp_cmd, shell=True) == 0:
  			print("cython returned an error, exiting setup.py")
  			exit(1)
  		print("_NetworKit.pyx cythonized", flush=True)
  
  def buildNetworKit(install_prefix, externalCore=False, withTests=False, rpath=None):
  	# Cythonize file
  	cythonizeFile("networkit/_NetworKit.pyx")
  	try:
  		os.makedirs(buildDirectory)
  	except FileExistsError:
  		pass
  	# Build cmake call
  	abs_prefix = os.path.join(os.getcwd(), install_prefix)
  	comp_cmd = ["cmake","-A","x64","-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
  	#Windows support
  	from distutils.sysconfig import get_config_var
  	
  	comp_cmd.append("-DNETWORKIT_PYTHON="+get_paths()['include']) #provide python.h files
  	comp_cmd.append("-DNETWORKIT_PYTHON_SOABI="+ get_config_var('EXT_SUFFIX').split('.')[1]      )#+get_config_var('SOABI')) #provide lib env specification
  	if externalCore:
  		comp_cmd.append("-DNETWORKIT_BUILD_CORE=OFF")
  	if ninja_available:
  		comp_cmd.append("-GNinja")
  	comp_cmd.append(os.getcwd()) #call CMakeLists.txt from networkit root
  	if rpath:
  		comp_cmd.append("-DNETWORKIT_PYTHON_RPATH="+rpath)
  	# Run cmake
  	print("initializing NetworKit compilation with: '{0}'".format(" ".join(comp_cmd)), flush=True)
  	if not subprocess.call(comp_cmd, cwd=buildDirectory, shell=True) == 0:
  	
  		print("cmake returned an error, exiting setup.py")
  		exit(1)
  	build_cmd = []
  	#windows support
  	#ninja is not tested for windows , thus it is not modified
  	if ninja_available:
  		build_cmd = ["ninja", "install", "-j"+str(jobs)]
  	else:
  		#build_cmd = ["make", "install", "-j"+str(jobs)]
  		#windows support
  		#no parallelism as in -jX in make
  		#TODO: little more search to put more usefull switches/flags in the msbuild command if available
  		build_cmd = ["msbuild", "/P:Configuration=Release", "INSTALL.vcxproj"]
  
  
  
  	print("Build with: '{0}'".format(" ".join(build_cmd)), flush=True)
  	if not subprocess.call(build_cmd, cwd=buildDirectory, shell=True) == 0:
  		print("Build tool returned an error, exiting setup.py")
  		exit(1)
  
  ################################################
  # custom build commands to integrate with setuptools
  ################################################
  
  # Unfortunately, there is not simple way to invoke external commands from setuptools.
  # Thus, we replace the 'build_ext' stage of setuptools completely.
  # This looks a bit messy as we need to make sure we satisfy the (undocumented) internal APIs
  # of setuptools (and distutils, which setuptools is based on).
  
  # Our build_ext command compiles NetworKit using cmake and installs it into a directory
  # supplied by distutils/setuptools. distutils/setuptools picks up all .so files from that
  # directory when creating a Python package so that we do not have to do any
  # additional installation.
  
  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"),
  		('rpath=', 'r', "additional custom rpath references")
  	]
  
  	def initialize_options(self):
  		# TODO: While we accept --include-dirs and --library-dirs, those options are not implemented yet.
  		self.build_lib = None # Output directory for libraries
  		self.build_temp = None # Temporary directory
  		self.inplace = False
  		self.include_dirs = None
  		self.library_dirs = None
  		self.networkit_external_core = False
  		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
  
  	# Returns the full Python module name of an extension.
  	# Prepends the ext_package setup() option to an extension (see distutils).
  	def get_ext_fullname(self, extname):
  		if self.package is not None:
  			return self.package + '.' + extname
  		return extname
  
  	# Returns the file name of the DSO implementing a module (see distutils).
  	def get_ext_filename(self, fullname):
  		return fullname + '.' + sysconfig.get_config_var('SOABI') + '.so'
  
  	def run(self):
  		# A generic build_ext command for cmake would iterate over all self.extensions.
  		# However, we know that we only want to build a single extension, i.e. NetworKit.
  		prefix = self.build_lib
  		if self.inplace:
  			# The --inplace implementation is less sophisticated than in distutils,
  			# but it should be sufficient for NetworKit.
  			prefix = self.distribution.src_root or os.getcwd()
  		buildNetworKit(prefix, externalCore=self.networkit_external_core, rpath=self.rpath)
  
  	def get_ext_fullpath(self, ext_name):
  		"""Returns the path of the filename for a given extension.
  		The file is located in `build_lib` or directly in the package
  		(inplace option).
  		"""
  		fullname = self.get_ext_fullname(ext_name)
  		modpath = fullname.split('.')
  		filename = self.get_ext_filename(modpath[-1])
  
  		if not self.inplace:
  			# no further work needed
  			# returning :
  			#   build_dir/package/path/filename
  			filename = os.path.join(*modpath[:-1]+[filename])
  			return os.path.join(self.build_lib, filename)
  
  		# the inplace option requires to find the package directory
  		# using the build_py command for that
  		package = '.'.join(modpath[0:-1])
  		build_py = self.get_finalized_command('build_py')
  		package_dir = os.path.abspath(build_py.get_package_dir(package))
  
  		# returning
  		#   package_dir/filename
  		return os.path.join(package_dir, filename)
  
  	def get_outputs(self):
  		# And build the list of output (built) filenames.  Note that this
  		# ignores the 'inplace' flag, and assumes everything goes in the
  		# "build" tree.
  		outputs = []
  		for ext in self.extensions:
  			outputs.append(self.get_ext_fullpath(ext.name))
  		return outputs
  
  ################################################
  # initialize python setup
  ################################################
  from setuptools import find_packages # in addition to setup
  import version
  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			= [Extension('_NetworKit', sources=[])],
  	test_suite			= 'nose.collector',
  	install_requires	= version.install_requires,
  	zip_safe			= False) # see https://cython.readthedocs.io/en/latest/src/reference/compilation.html
  
  ################################################
  # check for tkinter installation
  # cant be handled by install_requires because
  # tkinter is not part of pip
  ################################################
  try:
  	import tkinter #python3 only
  	del tkinter #python3 only
  except:
  	print("WARNING: _tkinter is necessary for networkit.profiling module if not used via jupyter.\nInstall tkinter if needed")
  