Add conan support

This commit is contained in:
Danny Robson 2020-10-19 07:46:18 +10:00
parent 04c832b0cd
commit 276921ab1a
6 changed files with 269 additions and 49 deletions

View File

@ -0,0 +1,17 @@
[settings]
os=Linux
arch=x86_64
compiler=clang
compiler.version=10
compiler.libcxx=libc++
build_type=Release
[options]
[build_requires]
[env]
CC=clang-10
CXX=clang++-10

View File

@ -0,0 +1,17 @@
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=10.2
compiler.libcxx=libstdc++11
build_type=Debug
[options]
[build_requires]
[env]
CC=gcc
CXX=g++

View File

@ -0,0 +1,17 @@
[settings]
os=Linux
arch=x86_64
compiler=gcc
compiler.version=10.2
compiler.libcxx=libstdc++11
build_type=Release
[options]
[build_requires]
[env]
CC=gcc
CXX=g++

View File

@ -0,0 +1,24 @@
toolchain=/usr/x86_64-w64-mingw32
target_host=x86_64-w64-mingw32
cc_compiler=gcc
cxx_compiler=g++
[env]
CONAN_CMAKE_FIND_ROOT_PATH=$toolchain
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
RANLIB=$target_host-ranlib
CC=$target_host-$cc_compiler
CXX=$target_host-$cxx_compiler
STRIP=$target_host-strip
RC=$target_host-windres
[settings]
os=Windows
arch=x86_64
compiler=gcc
compiler.version=10.1
compiler.libcxx=libstdc++11
build_type=Release

227
init.py
View File

@ -4,55 +4,174 @@ import sys
import os
import itertools
import multiprocessing
from dataclasses import dataclass, field
OPTIONS = {
# compiler
'gcc': {'vars': {'CMAKE_CXX_COMPILER': 'g++', 'CMAKE_C_COMPILER': 'gcc'}},
'clang': {'vars': {'CMAKE_CXX_COMPILER': 'clang++-10', 'CMAKE_C_COMPILER': 'clang-10'}},
from typing import Dict, List, Optional
# profile
'debug': {
'vars': {'CMAKE_BUILD_TYPE': 'Debug', 'LTO': 'OFF'},
CLANG_VERSION = 10
@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:
res = Option(
vars={**a.vars, **b.vars},
require=a.require+b.require,
)
replace = (
'args', 'build', 'platform', 'compiler', 'config', 'arch',
)
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'
},
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',
)
# -----------------------------------------------------------------------------
OPTIONS['debug'] = Option(
vars={
'CMAKE_BUILD_TYPE': 'Debug',
'LTO': 'OFF'
},
config='debug',
#'args': ['-G', '"Unix Makefiles"'],
#'build': [ "make", f"-j{multiprocessing.cpu_count()}" ],
)
OPTIONS['release'] = Option(
vars={
'CMAKE_BUILD_TYPE': 'Release',
'LTO': 'ON'
},
'release': {'vars': {'CMAKE_BUILD_TYPE': 'Release', 'LTO': 'ON'}},
config='release',
)
# sanitizer
'sanitizer': {'vars': {'SANITIZER': 'ON'}, 'require': {'PROFILE': 'release'}},
# wrappers
'iwyu': { 'vars': { 'CMAKE_CXX_INCLUDE_WHAT_YOU_USE': 'include-what-you-use' } },
'tidy': { 'vars': { 'CMAKE_CXX_CLANG_TIDY': ';'.join(['clang-tidy', '--quiet', '-checks=bugprone-*,clang-analyzer-*,performance-*,portability-*,readability-,', '-warnings-as-errors=' ]) } },
# build tools
'make': {
'args': [ '-G', '"Unix Makefiles"' ],
'build': [ "make", f"-j{multiprocessing.cpu_count()}" ],
OPTIONS['sanitizer'] = Option(
vars={
'SANITIZER': 'ON',
},
require=[
'release'
],
)
'ninja': {
'args': [ '-G', 'Ninja' ],
'build': [ 'ninja' ]
# -----------------------------------------------------------------------------
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',
)
# platforms
'mingw': { 'vars': { 'CMAKE_TOOLCHAIN_FILE': os.path.realpath(os.path.join(os.path.dirname(__file__), 'mingw.toolchain')) }, },
# Default parameters
'': {
'vars': {
# -----------------------------------------------------------------------------
DEFAULT_OPTION = Option(
vars={
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"TESTS": "ON",
},
'args': ['-G', 'Ninja'],
args=['-G', 'Ninja'],
'build': [ 'ninja' ],
},
}
build=[ 'ninja' ],
platform='linux',
compiler='gcc',
config='release',
arch='x86_64',
)
# #############################################################################
def split_all_path(path):
parts = []
@ -62,34 +181,60 @@ def split_all_path(path):
path = head
# #############################################################################
if __name__ == '__main__':
# Discover where we are, and where the source and build directories are
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)
# Build a list of the OPTION keys we're going to combine
accumulated = []
components = ['']
components = []
components += sys.argv[1:]
components += itertools.takewhile(lambda x: x in OPTIONS, split_all_path(os.getcwd()))
build = [ 'true' ]
# 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
for key in components:
obj = OPTIONS[key]
build = ['true']
vars = obj.get('vars', {})
args = obj.get('args', [])
build = obj.get('build', build)
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,
])
conan_build_profile = conan_host_profile
if accum.platform == 'mingw':
conan_build_profile = f'x86_64-gcc-linux-{accum.config}'
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)
accumulated += [f'"-D{key}={val}"' for key, val in vars.items()]
accumulated += args
cmds = [
"[[ -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/",
f"cmake {source_dir} {' '.join(accumulated)}",
' '.join(build)
' '.join(accum.build)
]
print(" && ".join(cmds))

View File

@ -111,7 +111,7 @@ def break_path_for_msys2(path):
# to ever deal with...
if is_really_windows():
separator = ';'
depsdir = [ 'bin', 'lib']
depsdir = ['bin']
# Add the likely path to runtime dependencies for Linux/mingw.
#