diff --git a/bin/BuildSystem/AutoToolsBuildSystem.py b/bin/BuildSystem/AutoToolsBuildSystem.py index 51bd57506..20a5d892a 100644 --- a/bin/BuildSystem/AutoToolsBuildSystem.py +++ b/bin/BuildSystem/AutoToolsBuildSystem.py @@ -1,126 +1,132 @@ # -*- coding: utf-8 -*- # definitions for the autotools build system -from BuildSystem.BuildSystemBase import * -from shells import * + +from BuildSystem.BuildSystemBase import BuildSystemBase +from CraftCore import CraftCore +from CraftOS.osutils import OsUtils +from shells import BashShell +import utils + +import os import glob import re class AutoToolsBuildSystem(BuildSystemBase): def __init__(self): BuildSystemBase.__init__(self, "autotools") self._shell = BashShell() self.platform = ""# hope for auto detection if CraftCore.compiler.isGCC() and not CraftCore.compiler.isNative() and CraftCore.compiler.isX86(): self.platform = "--host=i686-pc-linux-gnu " elif CraftCore.compiler.isWindows: if CraftCore.compiler.isX86(): self.platform = "--host=i686-w64-mingw32 --build=i686-w64-mingw32 --target=i686-w64-mingw32 " else: self.platform = "--host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 " @property def makeProgram(self): return "make" # make sure shell cant be overwritten @property def shell(self): return self._shell def configureDefaultDefines(self): """defining the default cmake cmd line""" return "" def configure(self): """configure the target""" self.enterBuildDir() configure = os.path.join(self.sourceDir(), self.subinfo.options.configure.projectFile or "configure") self.shell.environment["CFLAGS"] = self.subinfo.options.configure.cflags + " " + self.shell.environment["CFLAGS"] self.shell.environment["CXXFLAGS"] = self.subinfo.options.configure.cxxflags + " " + self.shell.environment["CXXFLAGS"] self.shell.environment["LDFLAGS"] = self.subinfo.options.configure.ldflags + " " + self.shell.environment["LDFLAGS"] autogen = os.path.join(self.sourceDir(), "autogen.sh") if self.subinfo.options.configure.bootstrap and os.path.exists(autogen): self.shell.execute(self.sourceDir(), autogen) elif self.subinfo.options.configure.autoreconf: includesArgs = "" if self.subinfo.options.configure.useDefaultAutoreconfIncludes: includes = [] for i in [f"{CraftCore.standardDirs.craftRoot()}/dev-utils/cmake/share", CraftCore.standardDirs.locations.data]: aclocalDir = self.shell.toNativePath(i) + "/aclocal" if os.path.isdir(aclocalDir): includes += [f" -I'{aclocalDir}'"] includesArgs = "".join(includes) self.shell.execute(self.sourceDir(), "autoreconf", self.subinfo.options.configure.autoreconfArgs + includesArgs) return self.shell.execute(self.buildDir(), configure, self.configureOptions(self)) def make(self, dummyBuildType=None): """Using the *make program""" self.enterBuildDir() command = self.makeProgram args = self.makeOptions(self.subinfo.options.make.args) # adding Targets later if not self.subinfo.options.useShadowBuild: if not self.shell.execute(self.buildDir(), self.makeProgram, "clean"): return False return self.shell.execute(self.buildDir(), command, args) def install(self): """Using *make install""" self.cleanImage() self.enterBuildDir() command = self.makeProgram args = self.makeOptions(self.subinfo.options.install.args) destDir = self.shell.toNativePath(self.installDir()) args += f" DESTDIR={destDir}" with utils.ScopedEnv({"DESTDIR" : destDir}): if not self.shell.execute(self.buildDir(), command, args): return False # la files aren't relocatable and until now we lived good without them laFiles = glob.glob(os.path.join(self.imageDir(), "**/*.la"), recursive=True) for laFile in laFiles: if not utils.deleteFile(laFile): return False return self._fixInstallPrefix(self.shell.toNativePath(self.installPrefix())) def unittest(self): """running unittests""" return self.shell.execute(self.buildDir(), self.makeProgram, "check") def configureOptions(self, defines=""): """returns default configure options""" options = BuildSystemBase.configureOptions(self) prefix = self.shell.toNativePath(self.installPrefix()) options += f" --prefix='{prefix}' " - if OsDetection.isWin() and not self.subinfo.options.configure.noDataRootDir: + if OsUtils.isWin() and not self.subinfo.options.configure.noDataRootDir: options += f" --datarootdir='{self.shell.toNativePath(CraftCore.standardDirs.locations.data)}' " options += self.platform return options; def ccacheOptions(self): return " CC='ccache gcc' CXX='ccache g++' " def copyToMsvcImportLib(self): - if not OsDetection.isWin(): + if not OsUtils.isWin(): return True reDlla = re.compile(r"\.dll\.a$") reLib = re.compile(r"^lib") for f in glob.glob(f"{self.installDir()}/lib/*.dll.a"): path, name = os.path.split(f) name = re.sub(reDlla, ".lib", name) name = re.sub(reLib, "", name) if not utils.copyFile(f, os.path.join(path, name), linkOnly=False): return False return True diff --git a/bin/shells.py b/bin/shells.py index 834dcf4be..c28747263 100644 --- a/bin/shells.py +++ b/bin/shells.py @@ -1,177 +1,181 @@ #!/usr/bin/env python """ provides shells """ -from Blueprints.CraftVersion import CraftVersion -from CraftStandardDirs import CraftStandardDirs -from CraftOS.OsDetection import OsDetection -from options import * import subprocess +import sys + +from CraftCore import CraftCore +from Blueprints.CraftVersion import CraftVersion +from CraftOS.osutils import OsUtils +import utils + +import os +import shutil class BashShell(object): def __init__(self): self._environment = {} self._useMSVCCompatEnv = False @property def useMSVCCompatEnv(self): return self._useMSVCCompatEnv @useMSVCCompatEnv.setter def useMSVCCompatEnv(self, b): self._useMSVCCompatEnv = b self._environment = {} @property def environment(self): if not self._environment: - mergeroot = self.toNativePath(CraftStandardDirs.craftRoot()) + mergeroot = self.toNativePath(CraftCore.standardDirs.craftRoot()) ldflags = f" -L{mergeroot}/lib " cflags = f" -I{mergeroot}/include " if CraftCore.compiler.isMacOS: # Only look for includes/libraries in the XCode SDK on MacOS to avoid errors with # libraries installed by homebrew (causes errors e.g. with iconv since headers will be # found in /usr/local/include first but libraries are searched for in /usr/lib before # /usr/local/lib. See https://langui.sh/2015/07/24/osx-clang-include-lib-search-paths/ if CraftCore.compiler.macUseSDK: sdkPath = CraftCore.cache.getCommandOutput("xcrun", "--show-sdk-path")[1].strip() deploymentFlag = "-mmacosx-version-min=" + CraftCore.compiler.macOSDeploymentTarget cflags = f" -isysroot {sdkPath} {deploymentFlag}" + cflags # See https://github.com/Homebrew/homebrew-core/issues/2674 for the -no_weak_imports flag ldflags = f" -isysroot {sdkPath} {deploymentFlag} -Wl,-no_weak_imports" + ldflags # Note: MACOSX_DEPLOYMENT_TARGET is set in utils.system() so doesn't need to be set here else: # Ensure that /usr/include comes before /usr/local/include in the header search path to avoid # pulling in headers from /usr/local/include (e.g. installed by homebrew) that will cause # linker errors later. cflags = " -isystem /usr/include " + cflags if CraftCore.compiler.isMSVC(): # based on Windows-MSVC.cmake if self.buildType == "Release": cflags += " -MD -O2 -Ob2 -DNDEBUG " elif self.buildType == "RelWithDebInfo": cflags += " -MD -Zi -O2 -Ob1 -DNDEBUG " ldflags += " -debug " elif self.buildType == "Debug": cflags += " -MDd -Zi -Ob0 -Od " ldflags += " -debug -pdbtype:sept " else: if self.buildType == "Release": cflags += " -O3 -DNDEBUG " if self.buildType == "RelWithDebInfo": cflags += " -O2 -g -DNDEBUG " elif self.buildType == "Debug": cflags += " -O0 -g3 " - if OsDetection.isWin(): + if OsUtils.isWin(): path = "/usr/local/bin:/usr/bin:/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl" if CraftCore.compiler.isMinGW(): gcc = shutil.which("gcc") if gcc: path = f"{self.toNativePath(os.path.dirname(gcc))}:{path}" for p in os.environ["PATH"].split(";"): path += f":{self.toNativePath(p)}" self._environment["PATH"] = path if "make" in self._environment: del self._environment["make"] # MSYSTEM is used by uname if CraftCore.compiler.isMinGW(): self._environment["MSYSTEM"] = f"MINGW{CraftCore.compiler.bits}_CRAFT" elif CraftCore.compiler.isMSVC(): self._environment["MSYSTEM"] = f"MSYS{CraftCore.compiler.bits}_CRAFT" if self.useMSVCCompatEnv and CraftCore.compiler.isMSVC(): automake = [] for d in os.scandir(os.path.join(os.path.dirname(self._findBash()), "..", "share")): if d.name.startswith("automake"): automake += [(d.name.rsplit("-")[1], os.path.realpath(d.path))] automake.sort(key=lambda x: CraftVersion(x[0])) latestAutomake = automake[-1][1] if False: cl = "clang-cl" else: cl = "cl" clWrapper = self.toNativePath(os.path.join(latestAutomake, "compile")) self._environment["LD"] = "link -nologo" self._environment["CC"] = f"{clWrapper} {cl} -nologo" self._environment["CXX"] = self._environment["CC"] self._environment["CPP"] = f"{cl} -nologo -EP" self._environment["CXXCPP"] = self._environment["CPP"] self._environment["NM"] = "dumpbin -symbols" self._environment["RC"] = f"windres -O COFF --target={'pe-i386' if CraftCore.compiler.isX86() else 'pe-x86-64'} --preprocessor='cl -nologo -EP -DRC_INVOKED -DWINAPI_FAMILY=0'" self._environment["STRIP"] = ":" self._environment["RANLIB"] = ":" self._environment["F77"] = "no" self._environment["FC"] = "no" cflags += (" -GR -W3 -EHsc" # dynamic and exceptions enabled " -D_USE_MATH_DEFINES -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS" " -wd4005" # don't warn on redefine " -wd4996" # The POSIX name for this item is deprecated. ) if CraftCore.compiler.getMsvcPlatformToolset() > 120: cflags += " -FS" self._environment["PKG_CONFIG_PATH"] = self.toNativePath( - os.path.join(CraftStandardDirs.craftRoot(), "lib", "pkgconfig")) + os.path.join(CraftCore.standardDirs.craftRoot(), "lib", "pkgconfig")) self._environment["CFLAGS"] = os.environ.get("CFLAGS", "").replace("$", "$$") + cflags self._environment["CXXFLAGS"] = os.environ.get("CXXFLAGS", "").replace("$", "$$") + cflags self._environment["LDFLAGS"] = os.environ.get("LDFLAGS", "").replace("$", "$$") + ldflags return self._environment @property def buildType(self): return CraftCore.settings.get("Compile", "BuildType", "RelWithDebInfo") @staticmethod def toNativePath(path): if OsUtils.isWin(): return OsUtils.toMSysPath(path) else: return path def _findBash(self): if OsUtils.isWin(): - msysdir = CraftStandardDirs.msysDir() + msysdir = CraftCore.standardDirs.msysDir() bash = CraftCore.cache.findApplication("bash", os.path.join(msysdir, "usr", "bin")) else: bash = CraftCore.cache.findApplication("bash") if not bash: CraftCore.log.critical("Failed to detect bash") return bash def execute(self, path, cmd, args="", **kwargs): # try to locate the command tmp = CraftCore.cache.findApplication(cmd) if tmp: cmd = tmp if CraftCore.compiler.isWindows: command = f"{self._findBash()} -c \"{self.toNativePath(cmd)} {args}\"" else: command = f"{self.toNativePath(cmd)} {args}" env = dict(kwargs.get("env", os.environ)) env.update(self.environment) - - return utils.system(command, cwd=path, env=env, **kwargs) + return utils.system(command, cwd=path, env=env,**kwargs) def login(self): if CraftCore.compiler.isMSVC(): self.useMSVCCompatEnv = True return self.execute(os.curdir, self._findBash(), "-i", displayProgress=True) def main(): shell = BashShell() shell.login() if __name__ == '__main__': main()