2019-02-22 12:46:26 +11:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import itertools
|
2019-08-05 08:15:25 +10:00
|
|
|
import multiprocessing
|
2020-10-19 08:46:18 +11:00
|
|
|
from dataclasses import dataclass, field
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
from typing import Dict, List, Optional
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-22 09:39:54 +11:00
|
|
|
CLANG_VERSION = 11
|
2020-10-19 08:46:18 +11:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class Option:
|
|
|
|
vars: Dict[str, str] = field(default_factory=dict)
|
|
|
|
compiler: str = None
|
|
|
|
config: str = None
|
|
|
|
require: List[str] = field(default_factory=list)
|
|
|
|
args: List[str] = field(default_factory=list)
|
|
|
|
build: List[str] = field(default_factory=list)
|
|
|
|
platform: str = None
|
|
|
|
arch: str = None
|
|
|
|
|
|
|
|
|
|
|
|
OPTIONS = dict()
|
|
|
|
|
|
|
|
|
|
|
|
def merge_option(a: Option, b: Option) -> Option:
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
res = Option(
|
|
|
|
vars={**a.vars, **b.vars},
|
|
|
|
require=a.require+b.require,
|
|
|
|
)
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
replace = (
|
|
|
|
'args', 'build', 'platform', 'compiler', 'config', 'arch',
|
|
|
|
)
|
2019-02-22 12:53:14 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
for f in replace:
|
|
|
|
setattr(
|
|
|
|
res,
|
|
|
|
f,
|
|
|
|
getattr(b, f, None) or getattr(a, f, None)
|
|
|
|
)
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
OPTIONS['gcc'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_CXX_COMPILER': 'g++',
|
|
|
|
'CMAKE_C_COMPILER': 'gcc'
|
2019-08-05 08:15:25 +10:00
|
|
|
},
|
2020-10-19 08:46:18 +11:00
|
|
|
compiler='gcc',
|
|
|
|
)
|
|
|
|
|
|
|
|
OPTIONS['clang'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_CXX_COMPILER': f'clang++-{CLANG_VERSION}',
|
|
|
|
'CMAKE_C_COMPILER': f'clang-{CLANG_VERSION}',
|
|
|
|
#'CMAKE_CXX_FLAGS': '-fuse-ld=lld',
|
|
|
|
},
|
|
|
|
compiler='clang',
|
|
|
|
)
|
|
|
|
|
2019-08-05 08:15:25 +10:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
OPTIONS['debug'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_BUILD_TYPE': 'Debug',
|
|
|
|
'LTO': 'OFF'
|
2019-08-05 08:15:25 +10:00
|
|
|
},
|
2020-10-19 08:46:18 +11:00
|
|
|
config='debug',
|
|
|
|
#'args': ['-G', '"Unix Makefiles"'],
|
|
|
|
#'build': [ "make", f"-j{multiprocessing.cpu_count()}" ],
|
|
|
|
)
|
2019-02-22 12:53:14 +11:00
|
|
|
|
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
OPTIONS['release'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_BUILD_TYPE': 'Release',
|
|
|
|
'LTO': 'ON'
|
|
|
|
},
|
|
|
|
config='release',
|
|
|
|
)
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2019-08-05 08:15:25 +10:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
OPTIONS['sanitizer'] = Option(
|
|
|
|
vars={
|
|
|
|
'SANITIZER': 'ON',
|
2019-02-22 12:46:26 +11:00
|
|
|
},
|
2020-10-19 08:46:18 +11:00
|
|
|
require=[
|
|
|
|
'release'
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
OPTIONS['iwyu'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_CXX_INCLUDE_WHAT_YOU_USE': 'include-what-you-use'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
TIDY_CHECKS=[
|
|
|
|
'bugprone-*',
|
|
|
|
'clang-analyzer-*',
|
|
|
|
'performance-*',
|
|
|
|
'portability-*',
|
|
|
|
'readability-',
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
OPTIONS['tidy'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_CXX_CLANG_TIDY': ';'.join([
|
|
|
|
'clang-tidy',
|
|
|
|
'--quiet',
|
|
|
|
'-checks=' + ','.join(TIDY_CHECKS),
|
|
|
|
'-warnings-as-errors=',
|
|
|
|
])
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
OPTIONS['make'] = Option(
|
|
|
|
args=[ '-G', '"Unix Makefiles"' ],
|
|
|
|
build=[ "make", f"-j{multiprocessing.cpu_count()}" ]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
OPTIONS['ninja'] = Option(
|
|
|
|
args=['-G', 'Ninja'],
|
|
|
|
build=['ninja']
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
OPTIONS['mingw'] = Option(
|
|
|
|
vars={
|
|
|
|
'CMAKE_TOOLCHAIN_FILE': os.path.realpath(
|
|
|
|
os.path.join(
|
|
|
|
os.path.dirname(__file__),
|
|
|
|
'mingw.toolchain')
|
|
|
|
)
|
|
|
|
},
|
|
|
|
compiler='gcc',
|
|
|
|
platform='mingw',
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
DEFAULT_OPTION = Option(
|
|
|
|
vars={
|
|
|
|
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
|
|
|
"TESTS": "ON",
|
|
|
|
},
|
|
|
|
|
|
|
|
args=['-G', 'Ninja'],
|
|
|
|
|
|
|
|
build=[ 'ninja' ],
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
platform='linux',
|
|
|
|
compiler='gcc',
|
|
|
|
config='release',
|
|
|
|
arch='x86_64',
|
|
|
|
)
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
|
|
|
|
# #############################################################################
|
2019-02-22 12:46:26 +11:00
|
|
|
def split_all_path(path):
|
|
|
|
parts = []
|
|
|
|
|
|
|
|
while len(path) > 1:
|
|
|
|
head,tail = os.path.split(path)
|
|
|
|
yield tail
|
|
|
|
path = head
|
|
|
|
|
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
# #############################################################################
|
2019-02-22 12:46:26 +11:00
|
|
|
if __name__ == '__main__':
|
2020-10-19 08:46:18 +11:00
|
|
|
# Discover where we are, and where the source and build directories are
|
2019-02-22 13:00:58 +11:00
|
|
|
self_path = os.path.realpath(__file__)
|
|
|
|
self_dir = os.path.dirname(self_path)
|
|
|
|
|
|
|
|
build_dir = os.path.realpath(os.getcwd())
|
|
|
|
source_dir = os.path.dirname(self_dir)
|
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
# Build a list of the OPTION keys we're going to combine
|
2019-02-22 12:46:26 +11:00
|
|
|
accumulated = []
|
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
components = []
|
2019-02-22 12:46:26 +11:00
|
|
|
components += sys.argv[1:]
|
|
|
|
components += itertools.takewhile(lambda x: x in OPTIONS, split_all_path(os.getcwd()))
|
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
# Fold in the dependencies of each OPTION
|
|
|
|
final_components = []
|
|
|
|
for i in components:
|
|
|
|
req = OPTIONS[i].require
|
|
|
|
if req is not None:
|
|
|
|
final_components.extend(req)
|
|
|
|
final_components.append(i)
|
|
|
|
components = final_components
|
|
|
|
|
|
|
|
build = ['true']
|
|
|
|
|
|
|
|
accum = DEFAULT_OPTION
|
|
|
|
for i in components:
|
|
|
|
accum = merge_option(accum, OPTIONS[i])
|
|
|
|
|
|
|
|
accumulated = [f'"-D{key}={val}"' for key, val in accum.vars.items()] + accum.args
|
|
|
|
|
|
|
|
conan_host_profile = '-'.join([
|
|
|
|
accum.arch,
|
|
|
|
accum.compiler,
|
|
|
|
accum.platform,
|
|
|
|
accum.config,
|
|
|
|
])
|
2019-08-05 08:15:25 +10:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
conan_build_profile = conan_host_profile
|
|
|
|
if accum.platform == 'mingw':
|
|
|
|
conan_build_profile = f'x86_64-gcc-linux-{accum.config}'
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2020-10-19 08:46:18 +11:00
|
|
|
profile_dir = os.path.join(source_dir, 'build', 'conan', 'profile')
|
|
|
|
prh = os.path.join(profile_dir, conan_host_profile)
|
|
|
|
prb = os.path.join(profile_dir, conan_build_profile)
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2019-04-04 11:40:02 +11:00
|
|
|
cmds = [
|
2020-10-19 08:46:18 +11:00
|
|
|
"[[ -v VIRTUAL_ENV ]]",
|
|
|
|
f"conan install {source_dir} -pr:h {prh} -pr:b {prb} --build=missing",
|
|
|
|
f"conan install {source_dir} -pr:h {prh} -pr:b {prb} --build=missing -g deploy -if deps/",
|
2019-04-04 11:40:02 +11:00
|
|
|
f"cmake {source_dir} {' '.join(accumulated)}",
|
2020-10-19 08:46:18 +11:00
|
|
|
' '.join(accum.build)
|
2019-04-04 11:40:02 +11:00
|
|
|
]
|
2019-02-22 12:46:26 +11:00
|
|
|
|
2019-04-04 11:40:02 +11:00
|
|
|
print(" && ".join(cmds))
|