aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/project/platform.py
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2021-03-20 13:16:15 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2021-03-20 14:34:32 +0300
commite731e6345d7fa1c2326b18c56f5dc361ea3adbfb (patch)
treecc72442867919028eda33b264c02eab47ca3a049 /project/platform.py
parentworkflows/basic: enable on windows-2016 (diff)
downloadcmake-common-e731e6345d7fa1c2326b18c56f5dc361ea3adbfb.tar.gz
cmake-common-e731e6345d7fa1c2326b18c56f5dc361ea3adbfb.zip
project.platform: add platform 'auto'
There were two problems: * On Windows, VS 2019 defaults to x64 while VS 2017 defaults to x86. * Too much focus on x86(-64) might mean that building stuff on ARM can become difficult. These were all addressed by adding a new platform 'auto'. On Windows, it defaults to picking either x64 or x86 (depending on the host arch) for both Boost and CMake. On Linux, it lets the compiler decide what arch to target.
Diffstat (limited to '')
-rw-r--r--project/platform.py105
1 files changed, 98 insertions, 7 deletions
diff --git a/project/platform.py b/project/platform.py
index d25827b..b19c93a 100644
--- a/project/platform.py
+++ b/project/platform.py
@@ -6,19 +6,29 @@
import argparse
from enum import Enum
import platform
+import os.path
+from project.os import on_windows
-class Platform(Enum):
- '''I only build for x86(-64), so here it goes.'''
+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 native():
+ 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
@@ -26,30 +36,111 @@ class Platform(Enum):
@staticmethod
def all():
- return tuple(Platform)
+ return Platform.X86, Platform.X64,
@staticmethod
def parse(s):
try:
if s == 'Win32':
- # AppVeyor convention:
+ # Visual Studio/AppVeyor convention:
return Platform.X86
return Platform(s)
except ValueError as e:
raise argparse.ArgumentTypeError(f'invalid platform: {s}') from e
- def get_address_model(self):
+ 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 get_cmake_arch(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 makefile_toolchain_file(self):
+ # For Makefile generators, we make a special toolchain 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}')
+
+ def cmake_msvc_arch(self):
+ return ['-A', self.msvc_arch()]
+
+ def cmake_msvc_args(self):
+ # When using the MSVC toolset, pass the appropriate -A flag.
+ args = []
+ args += self.cmake_msvc_arch()
+ return args