blob: 2c1ec943ecba2faefd5210fcbac624a1c3bda6a0 [file] [log] [blame]
hardlyb1e7e142014-08-06 00:43:51 +03001#!/usr/bin/python2.7
2
hardlyb1e7e142014-08-06 00:43:51 +03003import os
4import sys
onqtam778e94b2017-05-10 23:19:50 +03005import pprint
onqtamfea36c52017-05-10 22:52:57 +03006import argparse
onqtamfea36c52017-05-10 22:52:57 +03007import urllib
hardlyb1e7e142014-08-06 00:43:51 +03008from datetime import datetime
onqtam54565452016-05-19 18:09:20 +03009import shutil
10from time import sleep
hardlyb1e7e142014-08-06 00:43:51 +030011
onqtamfea36c52017-05-10 22:52:57 +030012# ==============================================================================
13# == ARGUMENTS =================================================================
14# ==============================================================================
onqtamc6555cf2016-09-20 15:07:28 +030015
onqtamfea36c52017-05-10 22:52:57 +030016def addCommonFlags(parser):
onqtam7d8ccec2017-05-11 19:31:15 +030017 parser.add_argument("compiler", choices=['msvc', 'gcc', 'clang'], default='msvc', help = "compiler to use")
onqtamfea36c52017-05-10 22:52:57 +030018 parser.add_argument("--debug", action = "store_true", help = "build in debug")
onqtamdc92a3c2017-05-11 00:08:50 +030019 parser.add_argument("--catch", action = "store_true", help = "use Catch instead of doctest")
20 parser.add_argument("--disabled", action = "store_true", help = "<doctest> define DOCTEST_CONFIG_DISABLE")
onqtamfea36c52017-05-10 22:52:57 +030021 parser.add_argument("--fast", action = "store_true", help = "define the doctest/Catch fast config identifier")
onqtam778e94b2017-05-10 23:19:50 +030022 parser.add_argument("--files", type=int, default=1, help = "number of source files (besides the implementation)")
23 parser.add_argument("--tests", type=int, default=1, help = "number of test cases per source file")
24 parser.add_argument("--checks", type=int, default=1, help = "number of asserts per test case")
onqtamfea36c52017-05-10 22:52:57 +030025 parser.add_argument("--asserts", choices=['normal', 'binary', 'fast'], default="normal",
26 help = "<doctest> type of assert used - Catch: only normal")
onqtam956d4ec2016-09-18 13:42:33 +030027
onqtamfea36c52017-05-10 22:52:57 +030028parser = argparse.ArgumentParser()
29subparsers = parser.add_subparsers()
30parser_c = subparsers.add_parser('compile', help='benchmark compile times')
31addCommonFlags(parser_c)
32parser_c.add_argument("--implement", action = "store_true", help = "implement the framework test runner")
33parser_c.add_argument("--header", action = "store_true", help = "include the framework header everywhere")
34parser_r = subparsers.add_parser('runtime', help='benchmark runtime')
35addCommonFlags(parser_r)
36parser_r.add_argument("--loop-iters", type=int, default=1000, help = "loop N times all asserts in each test case")
onqtam7d8ccec2017-05-11 19:31:15 +030037parser_r.add_argument("--info", action = "store_true", help = "log the loop variable with INFO()")
onqtamdf09f512016-09-15 13:43:50 +030038
onqtamfea36c52017-05-10 22:52:57 +030039def compile(args): args.compile = True; args.runtime = False
40def runtime(args): args.compile = False; args.runtime = True
41parser_c.set_defaults(func=compile)
42parser_r.set_defaults(func=runtime)
43args = parser.parse_args()
44args.func(args)
45
onqtam778e94b2017-05-10 23:19:50 +030046print("== PASSED OPTIONS TO BENCHMARK SCRIPT:")
47pprint.pprint(vars(args), width = 1)
onqtamfea36c52017-05-10 22:52:57 +030048
49# ==============================================================================
50# == SETUP ENVIRONMENT =========================================================
51# ==============================================================================
52
53# catch version
54catch_ver = "1.9.3"
55catch_header = "catch." + catch_ver + ".hpp"
56
57# get the catch header
58if not os.path.exists("catch." + catch_ver + ".hpp"):
59 urllib.urlretrieve ("https://raw.githubusercontent.com/philsquared/Catch/v" + catch_ver + "/single_include/catch.hpp", catch_header)
60
61# folder with generated code
62the_folder = 'project'
63
64# delete the folder
onqtam54565452016-05-19 18:09:20 +030065if os.path.exists(the_folder):
66 shutil.rmtree(the_folder)
hardlyb1e7e142014-08-06 00:43:51 +030067
onqtamfea36c52017-05-10 22:52:57 +030068# wait a bit or the script might fail...
69sleep(2)
hardlyb1e7e142014-08-06 00:43:51 +030070
onqtamfea36c52017-05-10 22:52:57 +030071# create the folder
onqtam54565452016-05-19 18:09:20 +030072if not os.path.exists(the_folder):
73 os.makedirs(the_folder)
hardlyb1e7e142014-08-06 00:43:51 +030074
onqtamfea36c52017-05-10 22:52:57 +030075# enter folder
76os.chdir(the_folder);
77
78# ==============================================================================
79# == DO STUFF ==================================================================
80# ==============================================================================
81
82# setup defines used
83defines = ""
onqtamdc92a3c2017-05-11 00:08:50 +030084if args.disabled:
onqtamfea36c52017-05-10 22:52:57 +030085 defines += "#define DOCTEST_CONFIG_DISABLE\n"
86if args.catch and args.fast:
87 defines += "#define CATCH_CONFIG_FAST_COMPILE\n"
88if not args.catch and args.fast:
89 defines += "#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS\n"
90
91define_implement = "#define DOCTEST_CONFIG_IMPLEMENT\n"
92if args.catch:
93 define_implement = "#define CATCH_CONFIG_RUNNER\n"
94
95# setup the macros used
96macro = " CHECK(a == b);\n"
onqtam7f2c0ba2017-05-12 03:10:01 +030097if args.runtime:
98 macro = " CHECK(i == i);\n"
onqtamfea36c52017-05-10 22:52:57 +030099if not args.catch and args.asserts == "binary":
100 macro = " CHECK_EQ(a, b);\n"
101if not args.catch and args.asserts == "fast":
102 macro = " FAST_CHECK_EQ(a, b);\n"
103
104# setup the header used
105include = '#include "doctest.h"\n'
106if args.catch:
107 include = '#include "' + catch_header + '"\n'
108
109# ==============================================================================
110# == GENERATE SOURCE CODE ======================================================
111# ==============================================================================
112
onqtam54565452016-05-19 18:09:20 +0300113# make the source files
onqtamfea36c52017-05-10 22:52:57 +0300114for i in range(0, args.files):
115 f = open(str(i) + '.cpp', 'w')
116 if args.runtime or args.header:
117 f.write(defines)
118 f.write(include)
119 for t in range(0, args.tests):
onqtam200e8882016-09-20 11:01:02 +0300120 f.write('TEST_CASE("") {\n')
onqtamfea36c52017-05-10 22:52:57 +0300121 f.write(' int a = 5;\n')
122 f.write(' int b = 5;\n')
123 if args.runtime and args.loop_iters > 0:
124 f.write(' for(int i = 0; i < ' + str(args.loop_iters) + '; ++i) {\n')
onqtam778e94b2017-05-10 23:19:50 +0300125 if args.runtime and args.info:
126 f.write(' INFO(i);\n')
onqtamfea36c52017-05-10 22:52:57 +0300127 for a in range(0, args.checks):
128 if args.runtime and args.loop_iters > 0:
129 f.write(' ')
130 f.write(macro)
131 if args.runtime and args.loop_iters > 0:
132 f.write(' }\n')
onqtam54565452016-05-19 18:09:20 +0300133 f.write('}\n\n')
134 f.write('int f' + str(i) + '() { return ' + str(i) + '; }\n\n')
135 f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300136
onqtam54565452016-05-19 18:09:20 +0300137# the main file
onqtamfea36c52017-05-10 22:52:57 +0300138f = open('main.cpp', 'w')
onqtamdc92a3c2017-05-11 00:08:50 +0300139if args.runtime or args.implement or args.header:
onqtamfea36c52017-05-10 22:52:57 +0300140 f.write(defines)
141 f.write(define_implement)
142 f.write(include)
onqtam54565452016-05-19 18:09:20 +0300143f.write('int main(int argc, char** argv) {\n')
onqtamdc92a3c2017-05-11 00:08:50 +0300144if args.runtime or args.implement or args.header:
onqtamfea36c52017-05-10 22:52:57 +0300145 if not args.catch: f.write(' int res = doctest::Context(argc, argv).run();\n')
onqtam54565452016-05-19 18:09:20 +0300146 else: f.write(' int res = Catch::Session().run(argc, argv);\n')
147else:
148 f.write(' int res = 0;\n')
onqtamfea36c52017-05-10 22:52:57 +0300149for i in range(0, args.files):
onqtam54565452016-05-19 18:09:20 +0300150 f.write(' int f' + str(i) + '(); res += f' + str(i) + '();\n')
151f.write(' return res;\n}\n')
152f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300153
onqtam54565452016-05-19 18:09:20 +0300154# the cmake file
onqtamfea36c52017-05-10 22:52:57 +0300155f = open('CMakeLists.txt', 'w')
onqtam54565452016-05-19 18:09:20 +0300156f.write('cmake_minimum_required(VERSION 2.8)\n\n')
onqtam94978212016-05-22 00:07:30 +0300157f.write('project(bench)\n\n')
onqtamfea36c52017-05-10 22:52:57 +0300158if not args.catch: f.write('include_directories("../../../doctest/")\n\n')
159else: f.write('include_directories("../")\n\n')
onqtam94978212016-05-22 00:07:30 +0300160f.write('add_executable(bench main.cpp\n')
onqtamfea36c52017-05-10 22:52:57 +0300161for i in range(0, args.files):
onqtam54565452016-05-19 18:09:20 +0300162 f.write(' ' + str(i) + '.cpp\n')
163f.write(')\n')
164f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300165
onqtamfea36c52017-05-10 22:52:57 +0300166# ==============================================================================
167# == INVOKE CMAKE ==============================================================
168# ==============================================================================
hardlyb1e7e142014-08-06 00:43:51 +0300169
onqtamdc92a3c2017-05-11 00:08:50 +0300170compiler = ""
onqtam7d8ccec2017-05-11 19:31:15 +0300171if args.compiler == 'clang':
onqtam7f2c0ba2017-05-12 03:10:01 +0300172 compiler = " -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-w"
onqtam7d8ccec2017-05-11 19:31:15 +0300173if args.compiler == 'gcc':
onqtam7f2c0ba2017-05-12 03:10:01 +0300174 compiler = " -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=-w"
onqtamdc92a3c2017-05-11 00:08:50 +0300175
onqtamfea36c52017-05-10 22:52:57 +0300176# setup cmake command
177cmake_command = 'cmake . -G "Visual Studio 15 Win64"' # MSVC 2017
onqtam7d8ccec2017-05-11 19:31:15 +0300178if args.compiler != 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300179 cmake_command = 'cmake . -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=' + ('Debug' if args.debug else 'Release')
180if os.name != "nt":
181 cmake_command = 'cmake . -DCMAKE_BUILD_TYPE=' + ('Debug' if args.debug else 'Release')
182
onqtamdc92a3c2017-05-11 00:08:50 +0300183os.system(cmake_command + compiler)
onqtamfea36c52017-05-10 22:52:57 +0300184
185# ==============================================================================
186# == BUILD PROJECT =============================================================
187# ==============================================================================
hardlyb1e7e142014-08-06 00:43:51 +0300188
onqtam54565452016-05-19 18:09:20 +0300189the_config = ''
onqtam7d8ccec2017-05-11 19:31:15 +0300190if args.compiler == 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300191 if args.debug: the_config = ' --config Debug'
192 else: the_config = ' --config Release'
hardlyb1e7e142014-08-06 00:43:51 +0300193
onqtamd4669c12016-05-22 00:24:44 +0300194# build it
195start = datetime.now()
onqtam54565452016-05-19 18:09:20 +0300196os.system('cmake --build .' + the_config)
197end = datetime.now()
onqtamd4669c12016-05-22 00:24:44 +0300198
onqtam7f2c0ba2017-05-12 03:10:01 +0300199if not args.runtime:
200 print("Time running compiler (+ linker) in seconds: " + str((end - start).total_seconds()))
hardlyb1e7e142014-08-06 00:43:51 +0300201
onqtamfea36c52017-05-10 22:52:57 +0300202# ==============================================================================
203# == RUN PROJECT ===============================================================
204# ==============================================================================
205
206if args.runtime:
207 start = datetime.now()
onqtam7d8ccec2017-05-11 19:31:15 +0300208 if args.compiler == 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300209 os.system(('Debug' if args.debug else 'Release') + '\\bench.exe')
210 elif os.name == "nt":
211 os.system('bench.exe')
212 else:
213 os.system('./bench')
214 end = datetime.now()
215
onqtam706eb4a2017-05-11 12:43:23 +0300216 print("Time running the tests in seconds: " + str((end - start).total_seconds()))
onqtamfea36c52017-05-10 22:52:57 +0300217
218# leave folder
hardlyb1e7e142014-08-06 00:43:51 +0300219os.chdir("../");
220
221
222
223
224
225
226
227
228
229
230
231
232
233