# Copyright (c) 2020 Egor Tensin # This file is part of the "cmake-common" project. # For details, see https://github.com/egor-tensin/cmake-common # Distributed under the MIT License. import argparse from enum import Enum import os.path import platform from project.os import on_windows class Platform(Enum): # I only build for x86(-64), so here it goes. X86 = "x86" X64 = "x64" # 'auto' means that no additional arguments will be passed to either # Boost's b2 nor CMake (except on Windows, see below). AUTO = "auto" def __str__(self): return str(self.value) @staticmethod def windows_native(): # On Windows, no explicit platform would mean x64 for VS 2019 and x86 # for VS 2017. To account for this discrepancy, it is assumed that # Windows builds can only target either x86 or x64 (which I don't think # is true?), and we default to x64 most of the time. # # Source: https://stackoverflow.com/a/12578715/514684 if platform.machine().endswith("64"): return Platform.X64 return Platform.X86 @staticmethod def all(): return Platform.X86, Platform.X64 @staticmethod def parse(s): try: if s == "Win32": # Visual Studio/AppVeyor convention: return Platform.X86 return Platform(s) except ValueError as e: raise argparse.ArgumentTypeError(f"invalid platform: {s}") from e def mingw_prefix(self): if self is Platform.AUTO: if on_windows(): # On Windows, use the host architecture. return Platform.windows_native().mingw_prefix() # On Linux, assume that the target is x64. return Platform.X64.mingw_prefix() if self is Platform.X86: return "i686" if self is Platform.X64: return "x86_64" raise NotImplementedError(f"unsupported platform: {self}") def address_model(self): """Maps to Boost's address-model.""" if self is Platform.AUTO: if on_windows(): # On Windows, use the host architecture. return Platform.windows_native().address_model() # On Linux, assume that the target is x64. raise RuntimeError( "cannot determine address model unless the target platform is specified explicitly" ) if self is Platform.X86: return 32 if self is Platform.X64: return 64 raise NotImplementedError(f"unsupported platform: {self}") def installdir(self, configuration): """Path to the installation directory inside the Boost build directory.""" if self is Platform.AUTO: if on_windows(): # On Windows, use the host architecture. return Platform.windows_native().installdir(configuration) # On Linux, the libraries are stored in install_dir/auto/CONFIGURATION/lib. return os.path.join("install_dir", str(self), str(configuration)) def boost_installdir(self, configuration): """Same as above, but for CMake.""" return self.installdir(configuration) def b2_address_model(self): if self is Platform.AUTO and not on_windows(): # On Linux, don't specify the architecture explicitly (it is # assumed that the host architecture will be targeted). return [] return [f"address-model={self.address_model()}"] def b2_installdir(self, configuration): return [f"--prefix={self.installdir(configuration)}"] def b2_args(self, configuration): args = [] args += self.b2_address_model() args += self.b2_installdir(configuration) return args def cmake_toolset_file(self): # For Makefile generators, we make a special toolset file that # specifies the -m32/-m64 flags, etc. if self is Platform.AUTO: # Let the compiler decide. return "" if self is Platform.X86: address_model = 32 elif self is Platform.X64: address_model = 64 else: raise NotImplementedError(f"unsupported platform: {self}") return f""" set(CMAKE_C_FLAGS -m{address_model}) set(CMAKE_CXX_FLAGS -m{address_model}) """ def msvc_arch(self): """Maps to CMake's -A argument for MSVC.""" if self is Platform.AUTO: if on_windows(): # On Windows, use the host architecture. return Platform.windows_native().msvc_arch() # I don't think the -A argument is supported on any generators # except the Visual Studio ones. raise RuntimeError( "-A parameter is only supported for Visual Studio generators" ) if self is Platform.X86: return "Win32" if self is Platform.X64: return "x64" raise NotImplementedError(f"unsupported platform: {self}")