blob: bc63c81838946b55fb9bf6474dca74c08baea624 [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")
onqtam87e80e52017-09-07 12:50:53 +030020 parser.add_argument("--disabled", action = "store_true", help = "DOCTEST_CONFIG_DISABLE / CATCH_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
onqtamc8692c42017-09-05 18:47:55 +030054catch_ver = "2.0.0-develop.3"
onqtamfea36c52017-05-10 22:52:57 +030055catch_header = "catch." + catch_ver + ".hpp"
56
57# get the catch header
onqtam25568b12018-05-31 19:09:59 +030058# if 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)
onqtamfea36c52017-05-10 22:52:57 +030060
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 = ""
onqtam87e80e52017-09-07 12:50:53 +030084if args.catch and args.disabled:
85 defines += "#define CATCH_CONFIG_DISABLE\n"
86if not args.catch and args.disabled:
onqtamfea36c52017-05-10 22:52:57 +030087 defines += "#define DOCTEST_CONFIG_DISABLE\n"
88if args.catch and args.fast:
89 defines += "#define CATCH_CONFIG_FAST_COMPILE\n"
90if not args.catch and args.fast:
91 defines += "#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS\n"
92
93define_implement = "#define DOCTEST_CONFIG_IMPLEMENT\n"
94if args.catch:
95 define_implement = "#define CATCH_CONFIG_RUNNER\n"
96
97# setup the macros used
98macro = " CHECK(a == b);\n"
onqtam7f2c0ba2017-05-12 03:10:01 +030099if args.runtime:
100 macro = " CHECK(i == i);\n"
onqtamfea36c52017-05-10 22:52:57 +0300101if not args.catch and args.asserts == "binary":
102 macro = " CHECK_EQ(a, b);\n"
103if not args.catch and args.asserts == "fast":
104 macro = " FAST_CHECK_EQ(a, b);\n"
105
106# setup the header used
107include = '#include "doctest.h"\n'
108if args.catch:
109 include = '#include "' + catch_header + '"\n'
110
111# ==============================================================================
112# == GENERATE SOURCE CODE ======================================================
113# ==============================================================================
114
onqtam54565452016-05-19 18:09:20 +0300115# make the source files
onqtamfea36c52017-05-10 22:52:57 +0300116for i in range(0, args.files):
117 f = open(str(i) + '.cpp', 'w')
118 if args.runtime or args.header:
119 f.write(defines)
120 f.write(include)
121 for t in range(0, args.tests):
onqtam200e8882016-09-20 11:01:02 +0300122 f.write('TEST_CASE("") {\n')
onqtamfea36c52017-05-10 22:52:57 +0300123 f.write(' int a = 5;\n')
124 f.write(' int b = 5;\n')
125 if args.runtime and args.loop_iters > 0:
126 f.write(' for(int i = 0; i < ' + str(args.loop_iters) + '; ++i) {\n')
onqtam778e94b2017-05-10 23:19:50 +0300127 if args.runtime and args.info:
128 f.write(' INFO(i);\n')
onqtamfea36c52017-05-10 22:52:57 +0300129 for a in range(0, args.checks):
130 if args.runtime and args.loop_iters > 0:
131 f.write(' ')
132 f.write(macro)
133 if args.runtime and args.loop_iters > 0:
134 f.write(' }\n')
onqtam54565452016-05-19 18:09:20 +0300135 f.write('}\n\n')
136 f.write('int f' + str(i) + '() { return ' + str(i) + '; }\n\n')
137 f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300138
onqtam54565452016-05-19 18:09:20 +0300139# the main file
onqtamfea36c52017-05-10 22:52:57 +0300140f = open('main.cpp', 'w')
onqtamdc92a3c2017-05-11 00:08:50 +0300141if args.runtime or args.implement or args.header:
onqtamfea36c52017-05-10 22:52:57 +0300142 f.write(defines)
143 f.write(define_implement)
144 f.write(include)
onqtam54565452016-05-19 18:09:20 +0300145f.write('int main(int argc, char** argv) {\n')
onqtamdc92a3c2017-05-11 00:08:50 +0300146if args.runtime or args.implement or args.header:
onqtamfea36c52017-05-10 22:52:57 +0300147 if not args.catch: f.write(' int res = doctest::Context(argc, argv).run();\n')
onqtam54565452016-05-19 18:09:20 +0300148 else: f.write(' int res = Catch::Session().run(argc, argv);\n')
149else:
150 f.write(' int res = 0;\n')
onqtamfea36c52017-05-10 22:52:57 +0300151for i in range(0, args.files):
onqtam54565452016-05-19 18:09:20 +0300152 f.write(' int f' + str(i) + '(); res += f' + str(i) + '();\n')
153f.write(' return res;\n}\n')
154f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300155
onqtam54565452016-05-19 18:09:20 +0300156# the cmake file
onqtamfea36c52017-05-10 22:52:57 +0300157f = open('CMakeLists.txt', 'w')
onqtam54565452016-05-19 18:09:20 +0300158f.write('cmake_minimum_required(VERSION 2.8)\n\n')
onqtam94978212016-05-22 00:07:30 +0300159f.write('project(bench)\n\n')
onqtam382b5b62017-09-11 12:53:51 +0300160f.write('if(NOT MSVC)\n')
161f.write('set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")\n')
162f.write('endif()\n\n')
onqtamfea36c52017-05-10 22:52:57 +0300163if not args.catch: f.write('include_directories("../../../doctest/")\n\n')
164else: f.write('include_directories("../")\n\n')
onqtam94978212016-05-22 00:07:30 +0300165f.write('add_executable(bench main.cpp\n')
onqtamfea36c52017-05-10 22:52:57 +0300166for i in range(0, args.files):
onqtam54565452016-05-19 18:09:20 +0300167 f.write(' ' + str(i) + '.cpp\n')
168f.write(')\n')
169f.close()
hardlyb1e7e142014-08-06 00:43:51 +0300170
onqtamfea36c52017-05-10 22:52:57 +0300171# ==============================================================================
172# == INVOKE CMAKE ==============================================================
173# ==============================================================================
hardlyb1e7e142014-08-06 00:43:51 +0300174
onqtamdc92a3c2017-05-11 00:08:50 +0300175compiler = ""
onqtam7d8ccec2017-05-11 19:31:15 +0300176if args.compiler == 'clang':
onqtam7f2c0ba2017-05-12 03:10:01 +0300177 compiler = " -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-w"
onqtam7d8ccec2017-05-11 19:31:15 +0300178if args.compiler == 'gcc':
onqtam7f2c0ba2017-05-12 03:10:01 +0300179 compiler = " -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=-w"
onqtamdc92a3c2017-05-11 00:08:50 +0300180
onqtamfea36c52017-05-10 22:52:57 +0300181# setup cmake command
182cmake_command = 'cmake . -G "Visual Studio 15 Win64"' # MSVC 2017
onqtam7d8ccec2017-05-11 19:31:15 +0300183if args.compiler != 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300184 cmake_command = 'cmake . -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=' + ('Debug' if args.debug else 'Release')
185if os.name != "nt":
186 cmake_command = 'cmake . -DCMAKE_BUILD_TYPE=' + ('Debug' if args.debug else 'Release')
187
onqtamdc92a3c2017-05-11 00:08:50 +0300188os.system(cmake_command + compiler)
onqtamfea36c52017-05-10 22:52:57 +0300189
190# ==============================================================================
191# == BUILD PROJECT =============================================================
192# ==============================================================================
hardlyb1e7e142014-08-06 00:43:51 +0300193
onqtam54565452016-05-19 18:09:20 +0300194the_config = ''
onqtam7d8ccec2017-05-11 19:31:15 +0300195if args.compiler == 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300196 if args.debug: the_config = ' --config Debug'
197 else: the_config = ' --config Release'
hardlyb1e7e142014-08-06 00:43:51 +0300198
onqtamd4669c12016-05-22 00:24:44 +0300199# build it
200start = datetime.now()
onqtam54565452016-05-19 18:09:20 +0300201os.system('cmake --build .' + the_config)
202end = datetime.now()
onqtamd4669c12016-05-22 00:24:44 +0300203
onqtam7f2c0ba2017-05-12 03:10:01 +0300204if not args.runtime:
205 print("Time running compiler (+ linker) in seconds: " + str((end - start).total_seconds()))
hardlyb1e7e142014-08-06 00:43:51 +0300206
onqtamfea36c52017-05-10 22:52:57 +0300207# ==============================================================================
208# == RUN PROJECT ===============================================================
209# ==============================================================================
210
211if args.runtime:
212 start = datetime.now()
onqtam7d8ccec2017-05-11 19:31:15 +0300213 if args.compiler == 'msvc':
onqtamfea36c52017-05-10 22:52:57 +0300214 os.system(('Debug' if args.debug else 'Release') + '\\bench.exe')
215 elif os.name == "nt":
216 os.system('bench.exe')
217 else:
218 os.system('./bench')
219 end = datetime.now()
220
onqtam706eb4a2017-05-11 12:43:23 +0300221 print("Time running the tests in seconds: " + str((end - start).total_seconds()))
onqtamfea36c52017-05-10 22:52:57 +0300222
223# leave folder
hardlyb1e7e142014-08-06 00:43:51 +0300224os.chdir("../");
225
226
227
228
229
230
231
232
233
234
235
236
237
238