sol2/bootstrap.py

197 lines
7.5 KiB
Python
Raw Normal View History

2014-08-11 07:59:03 +08:00
#!/usr/bin/env python
2014-06-06 06:37:46 +08:00
import ninja_syntax
import os, sys, glob, re
2014-06-06 06:37:46 +08:00
import itertools
import argparse
# utilities
def flags(*args):
return ' '.join(itertools.chain(*args))
def includes(l):
return ['-I"{}"'.format(x) for x in l]
def library_includes(l):
return ['-L"{}"'.format(x) for x in l]
def libraries(l):
return ['-l{}'.format(x) for x in l]
def dependencies(l):
return ['-isystem"{}"'.format(x) for x in l]
2014-06-06 06:37:46 +08:00
def object_file(f):
(root, ext) = os.path.splitext(f)
return os.path.join(objdir, root + '.o')
def replace_extension(f, e):
(root, ext) = os.path.splitext(f)
return root + e
# Default install dir
install_dir = os.path.join('/usr', 'include') if 'linux' in sys.platform else 'include'
# Compiler: Read from environment or defaulted
cxx = os.environ.get('CXX', "g++")
2014-06-06 06:37:46 +08:00
# command line stuff
parser = argparse.ArgumentParser()
parser.add_argument('--debug', action='store_true', help='compile with debug flags')
parser.add_argument('--cxx', metavar='<compiler>', help='compiler name to use (default: env.CXX=%s)' % cxx, default=cxx)
2016-03-12 00:34:44 +08:00
parser.add_argument('--cxx-flags', help='additional flags passed to the compiler', default='')
parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS)
Fix lack of inline in functions. diff --git a/bootstrap.py b/bootstrap.py index c24f6e5..1d6a0b3 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -37,6 +37,7 @@ parser = argparse.ArgumentParser() parser.add_argument('--debug', action='store_true', help='compile with debug flags') parser.add_argument('--cxx', metavar='<compiler>', help='compiler name to use (default: g++)', default='g++') parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS) +parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--lua-dir', metavar='<dir>', help='directory lua is in with include and lib subdirectories') parser.add_argument('--install-dir', metavar='<dir>', help='directory to install the headers to', default=install_dir); parser.epilog = """In order to install sol, administrative privileges might be required. @@ -80,6 +81,9 @@ if args.ci: else: ldflags.extend(libraries(['lua'])) +if args.testing: + cxxflags.append('-Wmissing-declarations') + if 'linux' in sys.platform: ldflags.extend(libraries(['dl'])) diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 694a2be..78f4dd4 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -33,12 +33,12 @@ namespace sol { namespace detail { #ifdef _MSC_VER -std::string get_type_name(const std::type_info& id) { +inline std::string get_type_name(const std::type_info& id) { return id.name(); } #elif defined(__GNUC__) || defined(__clang__) -std::string get_type_name(const std::type_info& id) { +inline std::string get_type_name(const std::type_info& id) { int status; char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); std::string realname = unmangled; @@ -50,7 +50,7 @@ std::string get_type_name(const std::type_info& id) { #error Compiler not supported for demangling #endif // compilers -std::string demangle(const std::type_info& id) { +inline std::string demangle(const std::type_info& id) { std::string realname = get_type_name(id); const static std::array<std::string, 2> removals = {{ "struct ", "class " }}; const static std::array<std::string, 2> replacements = {{ "::", "_" }}; diff --git a/sol/resolve.hpp b/sol/resolve.hpp index 0d849d0..1f6f606 100644 --- a/sol/resolve.hpp +++ b/sol/resolve.hpp @@ -28,66 +28,67 @@ namespace sol { namespace detail { template<typename R, typename... Args, typename F, typename = typename std::result_of<Unqualified<F>(Args...)>::type> -auto resolve_i(types<R(Args...)>, F&&)->R(Unqualified<F>::*)(Args...) { +inline auto resolve_i(types<R(Args...)>, F&&) -> R(Unqualified<F>::*)(Args...) { using Sig = R(Args...); typedef Unqualified<F> Fu; return static_cast<Sig Fu::*>(&Fu::operator()); } template<typename F, typename U = Unqualified<F>> -auto resolve_f(std::true_type, F&& f) -> decltype(resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { +inline auto resolve_f(std::true_type, F&& f) +-> decltype(resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { return resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); } template<typename F> -void resolve_f(std::false_type, F&&) { +inline void resolve_f(std::false_type, F&&) { static_assert(has_deducible_signature<F>::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); } template<typename F, typename U = Unqualified<F>> -auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signature<U> {}, std::forward<F>(f))) { +inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signature<U> {}, std::forward<F>(f))) { return resolve_f(has_deducible_signature<U> {}, std::forward<F>(f)); } template<typename... Args, typename F, typename R = typename std::result_of<F&(Args...)>::type> -auto resolve_i(types<Args...>, F&& f) -> decltype( resolve_i(types<R(Args...)>(), std::forward<F>(f))) { +inline auto resolve_i(types<Args...>, F&& f) -> decltype( resolve_i(types<R(Args...)>(), std::forward<F>(f))) { return resolve_i(types<R(Args...)>(), std::forward<F>(f)); } template<typename Sig, typename C> -Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { +inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { return mem_func_ptr; } template<typename Sig, typename C> -Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { +inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { return mem_variable_ptr; } } // detail template<typename... Args, typename R> -auto resolve(R fun_ptr(Args...)) -> R(*)(Args...) { +inline auto resolve(R fun_ptr(Args...)) -> R(*)(Args...) { return fun_ptr; } template<typename Sig> -Sig* resolve(Sig* fun_ptr) { +inline Sig* resolve(Sig* fun_ptr) { return fun_ptr; } template<typename... Args, typename R, typename C> -auto resolve(R(C::*mem_ptr)(Args...)) -> R(C::*)(Args...) { +inline auto resolve(R(C::*mem_ptr)(Args...)) -> R(C::*)(Args...) { return mem_ptr; } template<typename Sig, typename C> -Sig C::* resolve(Sig C::* mem_ptr) { +inline Sig C::* resolve(Sig C::* mem_ptr) { return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); } template<typename... Sig, typename F> -auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { +inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); } } // sol
2014-08-11 09:07:19 +08:00
parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS)
parser.add_argument('--lua-version', help='Lua version, e.g. lua53', default='lua53')
2016-02-25 21:28:07 +08:00
parser.add_argument('--lua-lib', help='lua library name (without the lib on *nix).', default='lua')
parser.add_argument('--lua-dir', metavar='<dir>', help='directory lua is in with include and lib subdirectories')
parser.add_argument('--install-dir', metavar='<dir>', help='directory to install the headers to', default=install_dir);
parser.epilog = """In order to install sol, administrative privileges might be required.
Note that installation is done through the 'ninja install' command. To uninstall, the
command used is 'ninja uninstall'. The default installation directory for this
system is {}""".format(install_dir)
2014-06-06 06:37:46 +08:00
args = parser.parse_args()
# general variables
include = [ '.', './include' ]
depends = [os.path.join('Catch', 'include')]
cxxflags = [ '-Wall', '-Wextra', '-Wpedantic', '-pedantic', '-pedantic-errors', '-std=c++14', '-ftemplate-depth=1024' ]
2016-03-12 00:34:44 +08:00
cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()])
ldflags = []
script_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
sol_dir = os.path.join(script_dir, 'sol')
sol_file = os.path.join(script_dir, 'sol.hpp')
copy_command = 'cp -rf {} $in && cp -f {} $in'.format(sol_dir, sol_file)
remove_command = 'rm -rf {} && rm -f {}'.format(os.path.join(args.install_dir, 'sol'), os.path.join(args.install_dir, 'sol.hpp'))
if sys.platform == 'win32':
copy_command = 'robocopy /COPYALL /E {} $in && robocopy /COPYALL {} $in'.format(sol_dir, sol_file)
remove_command = 'rmdir /S /Q {} && erase /F /S /Q /A {}'.format(os.path.join(args.install_dir, 'sol'),
os.path.join(args.install_dir, 'sol.hpp'))
2014-06-06 06:37:46 +08:00
2016-02-25 16:43:12 +08:00
if not args.lua_lib:
args.lua_lib = 'lua'
2014-06-06 06:37:46 +08:00
if args.debug:
cxxflags.extend(['-g', '-O0'])
else:
cxxflags.extend(['-DNDEBUG', '-O3'])
if args.lua_dir:
include.extend([os.path.join(args.lua_dir, 'include')])
ldflags.extend(library_includes([os.path.join(args.lua_dir, 'lib')]))
if 'linux' in sys.platform:
lua_version = os.environ.get('LUA_VERSION', args.lua_version)
if re.match(r'lua5[1-3]', lua_version):
# Using normal lua
lua_lib = lua_version[:-1] + '.' + lua_version[-1]
lua_incl = lua_lib
elif re.match(r'luajit5[1-3]', lua_version):
# luajit
lua_incl = 'luajit-2.0' # I don't get this..
lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1]
include.extend(['/usr/include/luajit-2.0/', '/usr/local/include/luajit-2.0/'])
2016-02-25 16:45:44 +08:00
else:
raise Exception('Unknown lua_version={}' % lua_version)
include.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl])
ldflags.extend(library_includes(['/usr/local/lib']))
ldflags.extend(libraries([lua_lib]))
elif 'darwin' in sys.platform:
# OSX
lua_version = os.environ.get('LUA_VERSION', args.lua_version)
if re.match(r'lua5[1-3]', lua_version):
# Using normal lua
lua_incl = lua_version[:-1] + '.' + lua_version[-1]
lua_lib = lua_version[:-2] + '.' + lua_version[-2] + '.' + lua_version[-1]
elif re.match(r'luajit5[1-3]', lua_version):
# luajit
lua_incl = 'luajit-2.0'
lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1]
else:
raise Exception('Unknown lua_version={}' % lua_version)
depends.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl])
ldflags.extend(library_includes(['/usr/local/lib']))
ldflags.extend(libraries([lua_lib]))
else:
ldflags.extend(libraries([args.lua_lib]))
2014-06-06 06:37:46 +08:00
Fix lack of inline in functions. diff --git a/bootstrap.py b/bootstrap.py index c24f6e5..1d6a0b3 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -37,6 +37,7 @@ parser = argparse.ArgumentParser() parser.add_argument('--debug', action='store_true', help='compile with debug flags') parser.add_argument('--cxx', metavar='<compiler>', help='compiler name to use (default: g++)', default='g++') parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS) +parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--lua-dir', metavar='<dir>', help='directory lua is in with include and lib subdirectories') parser.add_argument('--install-dir', metavar='<dir>', help='directory to install the headers to', default=install_dir); parser.epilog = """In order to install sol, administrative privileges might be required. @@ -80,6 +81,9 @@ if args.ci: else: ldflags.extend(libraries(['lua'])) +if args.testing: + cxxflags.append('-Wmissing-declarations') + if 'linux' in sys.platform: ldflags.extend(libraries(['dl'])) diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 694a2be..78f4dd4 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -33,12 +33,12 @@ namespace sol { namespace detail { #ifdef _MSC_VER -std::string get_type_name(const std::type_info& id) { +inline std::string get_type_name(const std::type_info& id) { return id.name(); } #elif defined(__GNUC__) || defined(__clang__) -std::string get_type_name(const std::type_info& id) { +inline std::string get_type_name(const std::type_info& id) { int status; char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); std::string realname = unmangled; @@ -50,7 +50,7 @@ std::string get_type_name(const std::type_info& id) { #error Compiler not supported for demangling #endif // compilers -std::string demangle(const std::type_info& id) { +inline std::string demangle(const std::type_info& id) { std::string realname = get_type_name(id); const static std::array<std::string, 2> removals = {{ "struct ", "class " }}; const static std::array<std::string, 2> replacements = {{ "::", "_" }}; diff --git a/sol/resolve.hpp b/sol/resolve.hpp index 0d849d0..1f6f606 100644 --- a/sol/resolve.hpp +++ b/sol/resolve.hpp @@ -28,66 +28,67 @@ namespace sol { namespace detail { template<typename R, typename... Args, typename F, typename = typename std::result_of<Unqualified<F>(Args...)>::type> -auto resolve_i(types<R(Args...)>, F&&)->R(Unqualified<F>::*)(Args...) { +inline auto resolve_i(types<R(Args...)>, F&&) -> R(Unqualified<F>::*)(Args...) { using Sig = R(Args...); typedef Unqualified<F> Fu; return static_cast<Sig Fu::*>(&Fu::operator()); } template<typename F, typename U = Unqualified<F>> -auto resolve_f(std::true_type, F&& f) -> decltype(resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { +inline auto resolve_f(std::true_type, F&& f) +-> decltype(resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { return resolve_i(types<function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); } template<typename F> -void resolve_f(std::false_type, F&&) { +inline void resolve_f(std::false_type, F&&) { static_assert(has_deducible_signature<F>::value, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); } template<typename F, typename U = Unqualified<F>> -auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signature<U> {}, std::forward<F>(f))) { +inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(has_deducible_signature<U> {}, std::forward<F>(f))) { return resolve_f(has_deducible_signature<U> {}, std::forward<F>(f)); } template<typename... Args, typename F, typename R = typename std::result_of<F&(Args...)>::type> -auto resolve_i(types<Args...>, F&& f) -> decltype( resolve_i(types<R(Args...)>(), std::forward<F>(f))) { +inline auto resolve_i(types<Args...>, F&& f) -> decltype( resolve_i(types<R(Args...)>(), std::forward<F>(f))) { return resolve_i(types<R(Args...)>(), std::forward<F>(f)); } template<typename Sig, typename C> -Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { +inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { return mem_func_ptr; } template<typename Sig, typename C> -Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { +inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { return mem_variable_ptr; } } // detail template<typename... Args, typename R> -auto resolve(R fun_ptr(Args...)) -> R(*)(Args...) { +inline auto resolve(R fun_ptr(Args...)) -> R(*)(Args...) { return fun_ptr; } template<typename Sig> -Sig* resolve(Sig* fun_ptr) { +inline Sig* resolve(Sig* fun_ptr) { return fun_ptr; } template<typename... Args, typename R, typename C> -auto resolve(R(C::*mem_ptr)(Args...)) -> R(C::*)(Args...) { +inline auto resolve(R(C::*mem_ptr)(Args...)) -> R(C::*)(Args...) { return mem_ptr; } template<typename Sig, typename C> -Sig C::* resolve(Sig C::* mem_ptr) { +inline Sig C::* resolve(Sig C::* mem_ptr) { return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); } template<typename... Sig, typename F> -auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { +inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); } } // sol
2014-08-11 09:07:19 +08:00
if args.testing:
cxxflags.append('-Wmissing-declarations')
if 'linux' in sys.platform:
ldflags.extend(libraries(['dl']))
2014-06-06 06:37:46 +08:00
builddir = 'bin'
objdir = 'obj'
if 'win32' in sys.platform:
tests = os.path.join(builddir, 'tests.exe')
else:
tests = os.path.join(builddir, 'tests')
2014-06-06 06:37:46 +08:00
tests_inputs = []
tests_object_files = []
for f in glob.glob('test*.cpp'):
obj = object_file(f)
tests_inputs.append(f)
tests_object_files.append(obj)
examples = []
examples_input = []
for f in glob.glob('examples/*.cpp'):
if 'win32' in sys.platform:
example = os.path.join(builddir, replace_extension(f, '.exe'))
else:
example = os.path.join(builddir, replace_extension(f, ''))
examples_input.append(f)
examples.append(example)
2014-06-06 06:37:46 +08:00
# ninja file
ninja = ninja_syntax.Writer(open('build.ninja', 'w'))
# variables
ninja.variable('ninja_required_version', '1.3')
ninja.variable('builddir', 'bin')
ninja.variable('cxx', args.cxx)
ninja.variable('cxxflags', flags(cxxflags + includes(include) + dependencies(depends)))
ninja.variable('ldflags', flags(ldflags))
ninja.newline()
# rules
ninja.rule('bootstrap', command = ' '.join(['python'] + sys.argv), generator = True)
ninja.rule('compile', command = '$cxx -MMD -MF $out.d -c $cxxflags -Werror $in -o $out',
deps = 'gcc', depfile = '$out.d',
description = 'compiling $in to $out')
ninja.rule('link', command = '$cxx $cxxflags $in -o $out $ldflags', description = 'creating $out')
ninja.rule('tests_runner', command = tests)
ninja.rule('examples_runner', command = 'cmd /c ' + (' && '.join(examples)) if 'win32' in sys.platform else ' && '.join(examples) )
ninja.rule('example', command = '$cxx $cxxflags -MMD -MF $out.d $in -o $out $ldflags',
deps = 'gcc', depfile = '$out.d',
description = 'compiling example $in to $out')
ninja.rule('installer', command = copy_command)
ninja.rule('uninstaller', command = remove_command)
2014-06-06 06:37:46 +08:00
ninja.newline()
# builds
ninja.build('build.ninja', 'bootstrap', implicit = sys.argv[0])
for obj, f in zip(tests_object_files, tests_inputs):
2014-06-06 06:37:46 +08:00
ninja.build(obj, 'compile', inputs = f)
for example, f in zip(examples, examples_input):
2014-06-06 06:37:46 +08:00
ninja.build(example, 'example', inputs = f)
ninja.build(tests, 'link', inputs = tests_object_files)
ninja.build('tests', 'phony', inputs = tests)
ninja.build('examples', 'phony', inputs = examples)
ninja.build('install', 'installer', inputs = args.install_dir)
ninja.build('uninstall', 'uninstaller')
ninja.build('run', 'tests_runner', implicit = 'tests')
ninja.build('run_examples', 'examples_runner', implicit = 'examples')
ninja.default('run run_examples')