def install(self): ret = CMakePackageBase.install(self) if OsUtils.isWin(): # Make installation movable, by providing rkward.ini with relative path to R rkward_ini = open( os.path.join(self.imageDir(), "bin", "rkward.ini"), "w") if CraftCore.compiler.isX64(): rkward_ini.write("R executable=../lib/R/bin/x64/R.exe\n") else: rkward_ini.write("R executable=../lib/R/bin/i386/R.exe\n") rkward_ini.close() elif OsUtils.isMac(): # Fix absolute library locations for R libs. Users may use RKWard with various versions of R (installed, separately), so # we cannot set a stable relative path, either. However, the rkward frontend makes sure to cd to the appropriate directory # when starting the backend, so the libs can be found by basename. rkward_rbackend = os.path.join(self.imageDir(), "lib", "libexec", "rkward.rbackend") for path in utils.getLibraryDeps(str(rkward_rbackend)): if path.startswith("/Library/Frameworks/R.framework"): utils.system([ "install_name_tool", "-change", path, os.path.join("@rpath", os.path.basename(path)), rkward_rbackend ]) # Finally tell the loader to look in the current working directory (as set by the frontend) utils.system( ["install_name_tool", "-add_rpath", ".", rkward_rbackend]) return ret
def createPackage(self): self.defines["executable"] = "bin\\rkward.exe" self.defines["icon"] = os.path.join(self.sourceDir(), "rkward", "icons", "app-icon", "rkward.ico") if OsUtils.isMac(): # We cannot reliably package R inside the bundle. Users will have to install it separately. self.ignoredPackages.append("binary/r-base") self.ignoredPackages.append("binary/mysql") self.ignoredPackages.append("data/hunspell-dictionaries") self.whitelist_file.append(os.path.join(self.packageDir(), 'whitelist.txt')) # Certain plugin files defeat codesigning on mac, which is picky about file names if OsUtils.isMac(): self.blacklist_file.append(os.path.join(self.packageDir(), 'blacklist_mac.txt')) return TypePackager.createPackage(self)
def configureOptions(self, defines=""): """returns default configure options""" options = BuildSystemBase.configureOptions(self) ## \todo why is it required to replace \\ by / ? options += " -DCMAKE_INSTALL_PREFIX=\"%s\"" % self.mergeDestinationDir( ).replace("\\", "/") options += " -DCMAKE_PREFIX_PATH=\"%s\"" % \ self.mergeDestinationDir().replace("\\", "/") if (not self.buildType() == None): options += " -DCMAKE_BUILD_TYPE=%s" % self.buildType() if craftCompiler.isGCC() and not craftCompiler.isNative(): options += " -DCMAKE_TOOLCHAIN_FILE=%s" % os.path.join( CraftStandardDirs.craftRoot(), "craft", "bin", "toolchains", "Toolchain-cross-mingw32-linux-%s.cmake" % craftCompiler.architecture) if craftSettings.getboolean("CMake", "KDE_L10N_AUTO_TRANSLATIONS", False): options += " -DKDE_L10N_AUTO_TRANSLATIONS=ON" if OsUtils.isWin(): options += " -DKDE_INSTALL_USE_QT_SYS_PATHS=ON" if OsUtils.isMac(): options += " -DKDE_INSTALL_BUNDLEDIR=\"%s/Applications/KDE\" -DAPPLE_SUPPRESS_X11_WARNING=ON" % \ self.mergeDestinationDir().replace("\\", "/") if not self.buildTests: options += " -DBUILD_TESTING=OFF " if self.subinfo.options.buildTools: options += " " + self.subinfo.options.configure.toolsDefine + " " if self.subinfo.options.buildStatic and self.subinfo.options.configure.staticArgs: options += " " + self.subinfo.options.configure.staticArgs + " " if self.subinfo.options.configure.onlyBuildTargets: options += self.__onlyBuildDefines( self.subinfo.options.configure.onlyBuildTargets) if self.subinfo.options.cmake.useCTest: options += " -DCMAKE_PROGRAM_PATH=\"%s\" " % \ (os.path.join(self.mergeDestinationDir(), "dev-utils", "svn", "bin").replace("\\", "/")) if craftCompiler.isIntel(): # this is needed because otherwise it'll detect the MSVC environment options += " -DCMAKE_CXX_COMPILER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "icl.exe").replace("\\", "/") options += " -DCMAKE_C_COMPILER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "icl.exe").replace("\\", "/") options += " -DCMAKE_LINKER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "xilink.exe").replace("\\", "/") options += " \"%s\"" % self.configureSourceDir() return options
def preArchive(self): if OsUtils.isMac(): # during packaging, the relative path between rkward and R gets changed, so we need to create an rkward.ini to help rkward find R rkward_dir = os.path.join(self.archiveDir(), "Applications", "KDE", "rkward.app", "Contents", "MacOS") utils.createDir(rkward_dir) rkward_ini = open(os.path.join(rkward_dir, "rkward.ini"), "w") rkward_ini.write("R executable=../Frameworks/R/R.framework/Resources/R\n") rkward_ini.close() return super().preArchive()
def preArchive(self): if OsUtils.isMac(): # On Mac there is no sane way to bundle R along with RKWard, so make the default behavior to detect an R installation, automatically. rkward_dir = os.path.join(self.archiveDir(), "Applications", "KDE", "rkward.app", "Contents", "MacOS") utils.createDir(rkward_dir) rkward_ini = open(os.path.join(rkward_dir, "rkward.ini"), "w") rkward_ini.write("R executable=auto\n") rkward_ini.close() return super().preArchive()
def _setupUnix(self): self.prependEnvVar("LD_LIBRARY_PATH", [ os.path.join(CraftStandardDirs.craftRoot(), "lib"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "x86_64-linux-gnu") ]) if OsUtils.isMac(): self.prependEnvVar( "DYLD_LIBRARY_PATH", [os.path.join(CraftStandardDirs.craftRoot(), "lib")])
def configureOptions(self, defines=""): """returns default configure options""" options = "-DBUILD_TESTING={testing} ".format( testing="ON" if self.buildTests else "OFF") options += BuildSystemBase.configureOptions(self) craftRoot = OsUtils.toUnixPath(CraftCore.standardDirs.craftRoot()) options += f" -DCMAKE_INSTALL_PREFIX=\"{craftRoot}\"" options += f" -DCMAKE_PREFIX_PATH=\"{craftRoot}\"" if (not self.buildType() == None): options += " -DCMAKE_BUILD_TYPE=%s" % self.buildType() if CraftCore.compiler.isGCC() and not CraftCore.compiler.isNative(): options += " -DCMAKE_TOOLCHAIN_FILE=%s" % os.path.join( CraftStandardDirs.craftRoot(), "craft", "bin", "toolchains", "Toolchain-cross-mingw32-linux-%s.cmake" % CraftCore.compiler.architecture) if CraftCore.settings.getboolean("CMake", "KDE_L10N_AUTO_TRANSLATIONS", False): options += " -DKDE_L10N_AUTO_TRANSLATIONS=ON" if OsUtils.isWin(): # people use InstallRequiredSystemLibraries.cmake wrong and unconditionally install the # msvc crt... options += " -DCMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP=ON" if OsUtils.isMac(): options += f" -DKDE_INSTALL_BUNDLEDIR=\"{OsUtils.toUnixPath(CraftCore.standardDirs.craftRoot())}/Applications/KDE\" -DAPPLE_SUPPRESS_X11_WARNING=ON" if CraftCore.compiler.macUseSDK: # Ensure that we don't depend on SDK features only present on newer systems options += " -DCMAKE_OSX_DEPLOYMENT_TARGET=" + CraftCore.compiler.macOSDeploymentTarget if CraftCore.compiler.isWindows or CraftCore.compiler.isMacOS: options += " -DKDE_INSTALL_USE_QT_SYS_PATHS=ON" if self.subinfo.options.buildTools: options += " " + self.subinfo.options.configure.toolsDefine + " " if self.subinfo.options.buildStatic and self.subinfo.options.configure.staticArgs: options += " " + self.subinfo.options.configure.staticArgs + " " if CraftCore.compiler.isIntel(): # this is needed because otherwise it'll detect the MSVC environment options += " -DCMAKE_CXX_COMPILER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "icl.exe").replace("\\", "/") options += " -DCMAKE_C_COMPILER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "icl.exe").replace("\\", "/") options += " -DCMAKE_LINKER=\"%s\" " % os.path.join( os.getenv("BIN_ROOT"), os.getenv("ARCH_PATH"), "xilink.exe").replace("\\", "/") options += " \"%s\"" % self.configureSourceDir() return options
def createPackage(self): self.defines["executable"] = "bin\\rkward.exe" self.defines["icon"] = os.path.join(self.sourceDir(), "rkward", "icons", "app-icon", "rkward.ico") self.ignoredPackages.append("binary/mysql") self.ignoredPackages.append("data/hunspell-dictionaries") self.whitelist_file.append(os.path.join(self.packageDir(), 'whitelist.txt')) if OsUtils.isMac(): return self.debugCreatePackageMac() else: return TypePackager.createPackage(self)
def __init__(self): CMakePackageBase.__init__(self) if OsUtils.isWin(): if CraftCore.compiler.isX64(): self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "x64") else: self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "i386") self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + OsUtils.toUnixPath(os.path.join(self.r_dir, "R.exe")) elif OsUtils.isMac(): rhome = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "R.framework", "Resources") self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + os.path.join(rhome, "R") + " -DNO_CHECK_R=1 -DR_HOME=" + rhome + " -DR_INCLUDEDIR=" + os.path.join(rhome, "include") + " -DR_SHAREDLIBDIR=" + os.path.join(rhome, "lib")
def setDependencies(self): self.buildDependencies["kde/frameworks/extra-cmake-modules"] = None self.buildDependencies["dev-utils/python2"] = None self.runtimeDependencies["libs/qt5/qtwebkit"] = None self.runtimeDependencies["virtual/base"] = None self.runtimeDependencies["kde/frameworks/tier1/kcoreaddons"] = None self.runtimeDependencies["kde/frameworks/tier1/kconfig"] = None self.runtimeDependencies["kde/frameworks/tier1/kwidgetsaddons"] = None self.runtimeDependencies["kde/frameworks/tier1/kguiaddons"] = None self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = None # hard dependency for now self.runtimeDependencies["extragear/kproperty"] = None # TODO Windows/Mac: add marble libs (we only need marble widget), for now marble libs are disabled there if not OsUtils.isWin() and not OsUtils.isMac(): self.runtimeDependencies["kde/applications/marble"] = None
def __init__(self): CMakePackageBase.__init__(self) self.translations = CraftPackageObject.get("extragear/rkward/rkward-translations").instance if OsUtils.isWin(): if CraftCore.compiler.isX64(): self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "x64") else: self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "i386") self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + OsUtils.toUnixPath(os.path.join(self.r_dir, "R.exe")) elif OsUtils.isMac(): self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "R.framework", "Resources", "R") if self.subinfo.hasSvnTarget: self.subinfo.options.configure.args += f" -DTRANSLATION_SRC_DIR={OsUtils.toUnixPath(self.translations.sourceDir())}"
def setDependencies(self): self.buildDependencies["extragear/rkward/rkward-translations"] = None self.runtimeDependencies["binary/r-base"] = None self.runtimeDependencies["kde/frameworks/tier1/ki18n"] = None self.runtimeDependencies["kde/frameworks/tier3/ktexteditor"] = None self.runtimeDependencies["kde/frameworks/tier1/kwindowsystem"] = None if CraftCore.compiler.isMinGW( ): # MinGW has not qtwebengine, but we can fall back to kdewebkit self.runtimeDependencies["kde/frameworks/tier3/kdewebkit"] = None else: self.runtimeDependencies['libs/qt5/qtwebengine'] = None # not strictly runtimeDependencies, but should be included in the package for plugins and extra functionality self.runtimeDependencies["kde/applications/kate"] = None if not OsUtils.isMac(): # kbibtex does not properly build on mac, yet, and is optional self.runtimeDependencies["extragear/kbibtex"] = None self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = None
def __init__(self): CMakePackageBase.__init__(self) if OsUtils.isWin(): if CraftCore.compiler.isX64(): self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "x64") else: self.r_dir = os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "R", "bin", "i386") self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + os.path.join( self.r_dir, "R.exe").replace("\\\\", "/") if CraftCore.compiler.isMSVC(): self.realconfigure = self.configure self.configure = self.msvcconfigure # NOTE: On Mac, we'll let RKWard try to auto-detect R (installed with officlal installer, or MacPorts, or something else) elif OsUtils.isMac(): self.subinfo.options.configure.args = " -DR_EXECUTABLE=" + os.path.join( CraftCore.standardDirs.craftRoot(), "lib", "R", "R.framework", "Resources", "R")
def setupEnvironment(self): originaleEnv = CaseInsensitiveDict(os.environ) for var, value in CraftCore.settings.getSection( "Environment"): # set and override existing values # the ini is case insensitive so sections are lowercase.... self.addEnvVar(var.upper(), value) self.prependEnvVar("PATH", os.path.dirname(sys.executable)) os.environ.update(self.getEnv()) self.addEnvVar("KDEROOT", CraftCore.standardDirs.craftRoot()) self.addEnvVar( "SSL_CERT_FILE", os.path.join(CraftCore.standardDirs.etcDir(), "cacert.pem")) self.addEnvVar( "REQUESTS_CA_BUNDLE", os.path.join(CraftCore.standardDirs.etcDir(), "cacert.pem")) if CraftCore.settings.getboolean("Compile", "UseCCache", False): self.addEnvVar( "CCACHE_DIR", CraftCore.settings.get( "Paths", "CCACHE_DIR", os.path.join(CraftCore.standardDirs.craftRoot(), "build", "CCACHE"))) if CraftCore.settings.getboolean("QtSDK", "Enabled", "false"): sdkPath = os.path.join(CraftCore.settings.get("QtSDK", "Path"), CraftCore.settings.get("QtSDK", "Version"), CraftCore.settings.get("QtSDK", "Compiler"), "bin") if not os.path.exists(sdkPath): log(f"Please ensure that you have installed the Qt SDK in {sdkPath}", critical=True) self.prependEnvVar("PATH", sdkPath) if OsUtils.isWin(): self._setupWin() elif OsUtils.isMac(): self._setupMac() else: self._setupUnix() PKG_CONFIG_PATH = collections.OrderedDict.fromkeys([ os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "pkgconfig") ]) if "PKG_CONFIG_PATH" in originaleEnv: PKG_CONFIG_PATH.update( collections.OrderedDict.fromkeys( originaleEnv["PKG_CONFIG_PATH"].split(os.path.pathsep))) else: pkgCOnfig = shutil.which("pkg-config", path=originaleEnv["PATH"]) if pkgCOnfig: out = self._getOutput( "pkg-config --variable pc_path pkg-config", shell=True) if out[0] == 0: PKG_CONFIG_PATH.update( collections.OrderedDict.fromkeys(out[1].split( os.path.pathsep))) self.prependEnvVar("PKG_CONFIG_PATH", os.path.pathsep.join(PKG_CONFIG_PATH.keys())) self.prependEnvVar("QT_PLUGIN_PATH", [ os.path.join(CraftCore.standardDirs.craftRoot(), "plugins"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "plugins"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib64", "plugins"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "x86_64-linux-gnu", "plugins"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "plugin") ]) self.prependEnvVar("QML2_IMPORT_PATH", [ os.path.join(CraftCore.standardDirs.craftRoot(), "qml"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "qml"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib64", "qml"), os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "x86_64-linux-gnu", "qml") ]) self.prependEnvVar("QML_IMPORT_PATH", os.environ["QML2_IMPORT_PATH"]) self.prependEnvVar("QT_DATA_DIRS", CraftCore.standardDirs.locations.data) if CraftCore.settings.getboolean("General", "UseSandboxConfig", True): self.setXDG() self.prependEnvVar("PATH", CraftCore.standardDirs.craftBin()) # add python site packages to pythonpath self.prependEnvVar( "PYTHONPATH", os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "site-packages")) # prepend our venv python self.prependEnvVar("PATH", [ os.path.join(CraftCore.standardDirs.etcDir(), f"virtualenv", "3", "Scripts" if CraftCore.compiler.isWindows else "bin"), os.path.join(CraftCore.standardDirs.etcDir(), f"virtualenv", "2", "Scripts" if CraftCore.compiler.isWindows else "bin") ]) # make sure that craftroot bin is the first to look for dlls etc self.prependEnvVar( "PATH", os.path.join(CraftCore.standardDirs.craftRoot(), "bin")) self.prependEnvVar( "PATH", os.path.join(CraftCore.standardDirs.craftRoot(), "dev-utils", "bin")) if CraftCore.compiler.isClang(): if OsUtils.isUnix() and CraftCore.settings.getboolean( "General", "UseSystemClang", True): self.addEnvVar("CC", "/usr/bin/clang") self.addEnvVar("CXX", "/usr/bin/clang++") else: if CraftCore.compiler.isMSVC(): self.addEnvVar("CC", "clang-cl") self.addEnvVar("CXX", "clang-cl") else: self.addEnvVar("CC", "clang") self.addEnvVar("CXX", "clang") elif CraftCore.compiler.isGCC(): if not CraftCore.compiler.isNative() and CraftCore.compiler.isX86( ): self.addEnvVar("CC", "gcc -m32") self.addEnvVar("CXX", "g++ -m32") self.addEnvVar("AS", "gcc -c -m32") else: self.addEnvVar("CC", "gcc") self.addEnvVar("CXX", "g++") if CraftCore.settings.getboolean( "General", "AllowAnsiColor", not CraftCore.settings.getboolean( "ContinuousIntegration", "Enabled", False)): # different non standard env switches self.addEnvVar("CLICOLOR_FORCE", "1") self.addEnvVar("CLICOLOR", "1") self.addEnvVar("ANSICON", "1") if CraftCore.compiler.isClang() and CraftCore.compiler.isMSVC(): self.prependEnvVar("CFLAGS", "-fcolor-diagnostics -fansi-escape-codes", sep=" ") self.prependEnvVar("CXXFLAGS", "-fcolor-diagnostics -fansi-escape-codes", sep=" ") elif CraftCore.compiler.isGCCLike(): self.prependEnvVar("CFLAGS", "-fdiagnostics-color=always", sep=" ") self.prependEnvVar("CXXFLAGS", "-fdiagnostics-color=always", sep=" ") if OsUtils.isWin(): self.addEnvVar( "TERM", "xterm-256color") # pretend to be a common smart terminal
def __init__(self): CMakePackageBase.__init__(self) if self.buildTarget != "1.0": self.subinfo.options.configure.args = "-DBUILD_GUI=ON" if OsUtils.isMac(): self.subinfo.options.configure.args += "-DDEPLOY_PLUGINS_WITH_BINARY=ON"
def setupEnvironment(self): for var, value in craftSettings.getSection("Environment"): # set and overide existing values self.addEnvVar(var, value) self.prependPath("PATH", os.path.dirname(sys.executable)) self.getEnv() self.checkForEvilApplication() self.addEnvVar("KDEROOT", CraftStandardDirs.craftRoot()) if craftSettings.getboolean("Compile", "UseCCache", False): self.addEnvVar("CCACHE_DIR", craftSettings.get("Paths", "CCACHE_DIR", os.path.join(CraftStandardDirs.craftRoot(), "build", "CCACHE"))) if self.version < 2: self.addEnvVar("GIT_SSH", "plink") self.addEnvVar("SVN_SSH", "plink") if not "HOME" in os.environ: self.addEnvVar("HOME", os.getenv("USERPROFILE")) self.prependPath("PKG_CONFIG_PATH", os.path.join(CraftStandardDirs.craftRoot(), "lib", "pkgconfig")) self.prependPath("QT_PLUGIN_PATH", [os.path.join(CraftStandardDirs.craftRoot(), "plugins"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "plugins"), os.path.join(CraftStandardDirs.craftRoot(), "lib64", "plugins"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "x86_64-linux-gnu", "plugins"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "plugin") ]) self.prependPath("QML2_IMPORT_PATH", [os.path.join(CraftStandardDirs.craftRoot(), "qml"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "qml"), os.path.join(CraftStandardDirs.craftRoot(), "lib64", "qml"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "x86_64-linux-gnu", "qml") ]) self.prependPath("QML_IMPORT_PATH", os.environ["QML2_IMPORT_PATH"]) if OsUtils.isUnix(): self.prependPath("LD_LIBRARY_PATH", [os.path.join(CraftStandardDirs.craftRoot(), "lib"), os.path.join(CraftStandardDirs.craftRoot(), "lib", "x86_64-linux-gnu")]) if OsUtils.isMac(): self.prependPath("DYLD_LIBRARY_PATH", [os.path.join(CraftStandardDirs.craftRoot(), "lib")]) self.setXDG() if craftSettings.getboolean("QtSDK", "Enabled", "false"): self.prependPath("PATH", os.path.join(craftSettings.get("QtSDK", "Path"), craftSettings.get("QtSDK", "Version"), craftSettings.get("QtSDK", "Compiler"), "bin")) if craftCompiler.isMinGW(): if not craftSettings.getboolean("QtSDK", "Enabled", "false"): if craftCompiler.isX86(): self.prependPath("PATH", os.path.join(CraftStandardDirs.craftRoot(), "mingw", "bin")) else: self.prependPath("PATH", os.path.join(CraftStandardDirs.craftRoot(), "mingw64", "bin")) else: compilerName = craftSettings.get("QtSDK", "Compiler") compilerMap = {"mingw53_32": "mingw530_32"} self.prependPath("PATH", os.path.join(craftSettings.get("QtSDK", "Path"), "Tools", compilerMap.get(compilerName, compilerName), "bin")) if OsUtils.isUnix(): self.prependPath("PATH", CraftStandardDirs.craftBin()) self.prependPath("PATH", os.path.join(CraftStandardDirs.craftRoot(), "dev-utils", "bin")) # make sure thate craftroot bin is the first to look for dlls etc self.prependPath("PATH", os.path.join(CraftStandardDirs.craftRoot(), "bin")) # add python site packages to pythonpath self.prependPath("PythonPath", os.path.join(CraftStandardDirs.craftRoot(), "lib", "site-packages"))