aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/project
diff options
context:
space:
mode:
Diffstat (limited to 'project')
-rw-r--r--project/boost/toolchain.py23
-rw-r--r--project/ci/appveyor/cmake.py3
-rw-r--r--project/ci/travis/cmake.py6
-rw-r--r--project/cmake/build.py40
-rw-r--r--project/cmake/toolchain.py105
-rw-r--r--project/mingw.py37
-rw-r--r--project/platform.py8
7 files changed, 184 insertions, 38 deletions
diff --git a/project/boost/toolchain.py b/project/boost/toolchain.py
index cacc2c2..a77c073 100644
--- a/project/boost/toolchain.py
+++ b/project/boost/toolchain.py
@@ -18,7 +18,7 @@ import abc
from contextlib import contextmanager
import logging
-import project.os
+import project.mingw
from project.utils import temp_file
@@ -62,27 +62,8 @@ class MinGW(Toolchain):
return [f'--user-config={self.config_path}', f'toolset=gcc-{MinGW.TAG}']
@staticmethod
- def _get_compiler_prefix(platform):
- target_arch = platform.get_address_model()
- if target_arch == 32:
- return 'i686'
- if target_arch == 64:
- return 'x86_64'
- raise RuntimeError(f'unexpected address model: {target_arch}')
-
- @staticmethod
- def _get_compiler_path(platform):
- prefix = MinGW._get_compiler_prefix(platform)
- ext = ''
- if project.os.on_windows_like():
- # Boost.Build wants the .exe extension at the end on Cygwin.
- ext = '.exe'
- path = f'{prefix}-w64-mingw32-g++{ext}'
- return path
-
- @staticmethod
def _format_mingw_user_config(platform):
- compiler = MinGW._get_compiler_path(platform)
+ compiler = project.mingw.get_gxx(platform)
features = {
'target-os': 'windows',
'address-model': platform.get_address_model(),
diff --git a/project/ci/appveyor/cmake.py b/project/ci/appveyor/cmake.py
index c3d55d0..c1b851c 100644
--- a/project/ci/appveyor/cmake.py
+++ b/project/ci/appveyor/cmake.py
@@ -114,12 +114,13 @@ def build_appveyor(argv=None):
args = _parse_args(argv)
_check_appveyor()
- cmake_args = ['-G', str(_get_generator()), '-A', str(_get_platform())]
+ cmake_args = ['-G', str(_get_generator())]
cmake_args += args.cmake_args
params = BuildParameters(_get_src_dir(),
build_dir=_get_build_dir(),
install_dir=args.install_dir,
+ platform=_get_platform(),
configuration=_get_configuration(),
cmake_args=cmake_args)
build(params)
diff --git a/project/ci/travis/cmake.py b/project/ci/travis/cmake.py
index 1d6eed4..47177bc 100644
--- a/project/ci/travis/cmake.py
+++ b/project/ci/travis/cmake.py
@@ -19,6 +19,7 @@ import sys
from project.cmake.build import BuildParameters, build
from project.configuration import Configuration
+from project.platform import Platform
from project.utils import setup_logging
@@ -41,6 +42,10 @@ def _get_build_dir():
return os.path.join(_env('HOME'), 'build')
+def _get_platform():
+ return Platform.parse(_env('platform'))
+
+
def _get_configuration():
return Configuration.parse(_env('configuration'))
@@ -68,6 +73,7 @@ def build_travis(argv=None):
params = BuildParameters(_get_src_dir(),
build_dir=_get_build_dir(),
install_dir=args.install_dir,
+ platform=_get_platform(),
configuration=_get_configuration(),
cmake_args=args.cmake_args)
build(params)
diff --git a/project/cmake/build.py b/project/cmake/build.py
index 101a4ea..5127c3d 100644
--- a/project/cmake/build.py
+++ b/project/cmake/build.py
@@ -17,18 +17,6 @@ A simple usage example:
$ ./path/to/somewhere/bin/foo
foo
-
-Picking the target platform is build system-specific. On Visual Studio, pass
-the target platform using the `-A` flag like this:
-
- > python -m project.cmake.build --install path\to\somewhere -- examples\simple -A Win32
- ...
-
-Using GCC-like compilers, the best way is to use CMake toolchain files (see
-toolchains/cmake in this repository for examples).
-
- $ python -m project.cmake.build --install path/to/somewhere -- examples/simple -D CMAKE_TOOLCHAIN_FILE="$( pwd )/toolchains/mingw-x86.cmake"
- ...
'''
import argparse
@@ -39,7 +27,9 @@ import os.path
import sys
import tempfile
+from project.cmake.toolchain import Toolchain
from project.configuration import Configuration
+from project.platform import Platform
from project.utils import normalize_path, run, setup_logging
@@ -52,7 +42,8 @@ def run_cmake(cmake_args):
class GenerationPhase:
def __init__(self, src_dir, build_dir, install_dir=None,
- configuration=DEFAULT_CONFIGURATION, cmake_args=None):
+ platform=None, configuration=DEFAULT_CONFIGURATION,
+ mingw=False, cmake_args=None):
src_dir = normalize_path(src_dir)
build_dir = normalize_path(build_dir)
if install_dir is not None:
@@ -62,20 +53,24 @@ class GenerationPhase:
self.src_dir = src_dir
self.build_dir = build_dir
self.install_dir = install_dir
+ self.platform = platform
self.configuration = configuration
+ self.mingw = mingw
self.cmake_args = cmake_args
- def _cmake_args(self):
+ def _cmake_args(self, toolchain):
result = []
if self.install_dir is not None:
result += ['-D', f'CMAKE_INSTALL_PREFIX={self.install_dir}']
+ result += toolchain.get_cmake_args()
result += ['-D', f'CMAKE_BUILD_TYPE={self.configuration}']
result += self.cmake_args
result += [f'-B{self.build_dir}', f'-H{self.src_dir}']
return result
def run(self):
- run_cmake(self._cmake_args())
+ with Toolchain.detect(self.platform, self.build_dir, mingw=self.mingw) as toolchain:
+ run_cmake(self._cmake_args(toolchain))
class BuildPhase:
@@ -101,7 +96,8 @@ class BuildPhase:
class BuildParameters:
def __init__(self, src_dir, build_dir=None, install_dir=None,
- configuration=DEFAULT_CONFIGURATION, cmake_args=None):
+ platform=None, configuration=DEFAULT_CONFIGURATION,
+ mingw=False, cmake_args=None):
src_dir = normalize_path(src_dir)
if build_dir is not None:
@@ -113,7 +109,9 @@ class BuildParameters:
self.src_dir = src_dir
self.build_dir = build_dir
self.install_dir = install_dir
+ self.platform = platform
self.configuration = configuration
+ self.mingw = mingw
self.cmake_args = cmake_args
@staticmethod
@@ -140,7 +138,9 @@ def build(params):
with params.create_build_dir() as build_dir:
gen_phase = GenerationPhase(params.src_dir, build_dir,
install_dir=params.install_dir,
+ platform=params.platform,
configuration=params.configuration,
+ mingw=params.mingw,
cmake_args=params.cmake_args)
gen_phase.run()
build_phase = BuildPhase(build_dir, install_dir=params.install_dir,
@@ -164,11 +164,19 @@ def _parse_args(argv=None):
type=normalize_path,
help='install directory')
+ platform_options = '/'.join(map(str, Platform.all()))
configuration_options = '/'.join(map(str, Configuration.all()))
+
+ parser.add_argument('--platform', metavar='PLATFORM',
+ type=Platform.parse,
+ help=f'target platform ({platform_options})')
parser.add_argument('--configuration', metavar='CONFIG',
type=Configuration.parse, default=DEFAULT_CONFIGURATION,
help=f'build configuration ({configuration_options})')
+ parser.add_argument('--mingw', action='store_true',
+ help='build using MinGW-w64')
+
parser.add_argument('src_dir', metavar='DIR',
type=normalize_path,
help='source directory')
diff --git a/project/cmake/toolchain.py b/project/cmake/toolchain.py
new file mode 100644
index 0000000..073cd1b
--- /dev/null
+++ b/project/cmake/toolchain.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+# 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 abc
+from contextlib import contextmanager
+import os.path
+
+import project.mingw
+from project.platform import Platform
+from project.os import on_windows
+
+
+class Toolchain(abc.ABC):
+ @abc.abstractmethod
+ def get_cmake_args(self):
+ pass
+
+ @staticmethod
+ @contextmanager
+ def detect(platform, build_dir, mingw=False):
+ if mingw:
+ with MinGW.setup(platform, build_dir) as toolchain:
+ yield toolchain
+ return
+
+ if on_windows():
+ # MSVC is assumed.
+ if platform is None:
+ yield Native()
+ return
+ yield MSVC(platform)
+ return
+
+ with GCC.setup(platform, build_dir) as toolchain:
+ yield toolchain
+ return
+
+
+class Native(Toolchain):
+ def get_cmake_args(self):
+ return []
+
+
+class MSVC(Toolchain):
+ def __init__(self, platform):
+ self.platform = platform
+
+ def get_cmake_args(self):
+ return ['-A', self.platform.get_cmake_arch()]
+
+
+class File(Toolchain):
+ def __init__(self, path):
+ self.path = path
+
+ @staticmethod
+ def _get_path(build_dir):
+ return os.path.join(build_dir, 'custom_toolchain.cmake')
+
+ def get_cmake_args(self):
+ return ['-D', f'CMAKE_TOOLCHAIN_FILE={self.path}']
+
+
+class GCC(File):
+ @staticmethod
+ def _format(platform):
+ return f'''
+set(CMAKE_C_COMPILER gcc)
+set(CMAKE_C_FLAGS -m{platform.get_address_model()})
+set(CMAKE_CXX_COMIPLER g++)
+set(CMAKE_CXX_FLAGS -m{platform.get_address_model()})
+'''
+
+ @staticmethod
+ @contextmanager
+ def setup(platform, build_dir):
+ if platform is None:
+ yield Native()
+ return
+ path = File._get_path(build_dir)
+ with open(path, mode='w') as file:
+ file.write(GCC._format(platform))
+ yield GCC(path)
+
+
+class MinGW(File):
+ @staticmethod
+ def _format(platform):
+ return f'''
+set(CMAKE_C_COMPILER {project.mingw.get_gcc(platform)})
+set(CMAKE_CXX_COMPILER {project.mingw.get_gxx(platform)})
+set(CMAKE_RC_COMILER {project.mingw.get_windres(platform)})
+set(CMAKE_SYSTEM_NAME Windows)
+'''
+
+ @staticmethod
+ @contextmanager
+ def setup(platform, build_dir):
+ platform = platform or Platform.native()
+ path = File._get_path(build_dir)
+ with open(path, mode='w') as file:
+ file.write(MinGW._format(platform))
+ yield MinGW(path)
diff --git a/project/mingw.py b/project/mingw.py
new file mode 100644
index 0000000..1e136cd
--- /dev/null
+++ b/project/mingw.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+# This file is part of the "cmake-common" project.
+# For details, see https://github.com/egor-tensin/cmake-common.
+# Distributed under the MIT License.
+
+from project.os import on_windows_like
+
+
+def _get_compiler_prefix(platform):
+ target_arch = platform.get_address_model()
+ if target_arch == 32:
+ return 'i686'
+ if target_arch == 64:
+ return 'x86_64'
+ raise RuntimeError(f'unexpected address model: {target_arch}')
+
+
+def _get(platform, what):
+ prefix = _get_compiler_prefix(platform)
+ ext = ''
+ if on_windows_like():
+ # Boost.Build wants the .exe extension at the end on Cygwin.
+ ext = '.exe'
+ path = f'{prefix}-w64-mingw32-{what}{ext}'
+ return path
+
+
+def get_gcc(platform):
+ return _get(platform, 'gcc')
+
+
+def get_gxx(platform):
+ return _get(platform, 'g++')
+
+
+def get_windres(platform):
+ return _get(platform, 'windres')
diff --git a/project/platform.py b/project/platform.py
index 249238e..8eb7f3e 100644
--- a/project/platform.py
+++ b/project/platform.py
@@ -45,3 +45,11 @@ class Platform(Enum):
if self is Platform.X64:
return 64
raise NotImplementedError(f'unsupported platform: {self}')
+
+ def get_cmake_arch(self):
+ '''Maps to CMake's -A argument for MSVC.'''
+ if self is Platform.X86:
+ return 'Win32'
+ if self is Platform.X64:
+ return 'x64'
+ raise NotImplementedError(f'unsupported platform: {self}')