# 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 stagedir(self, configuration): '''Path to the built libraries inside the Boost build directory.''' if self is Platform.AUTO: if on_windows(): # On Windows, use the host architecture. return Platform.windows_native().stagedir(configuration) # On Linux, the libraries are stored in stage/auto/CONFIGURATION/lib. return os.path.join('stage', str(self), str(configuration)) def boost_librarydir(self, configuration): '''Same as above, but for CMake; adds /lib/ at the end.''' return os.path.join(self.stagedir(configuration), 'lib') 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_stagedir(self, configuration): return [f'--stagedir={self.stagedir(configuration)}'] def b2_args(self, configuration): args = [] args += self.b2_address_model() args += self.b2_stagedir(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}')