1*baec84f2Syuangongji#!/usr/bin/env python3 2*baec84f2Syuangongji# 3*baec84f2Syuangongji# Check if find_package(Libevent COMPONENTS xxx) can get the correct library. 4*baec84f2Syuangongji# Note: this script has only been tested on python3. 5*baec84f2Syuangongji# Usage: 6*baec84f2Syuangongji# cd cmake-build-dir 7*baec84f2Syuangongji# cmake <options> .. && cmake --build . 8*baec84f2Syuangongji# python /path/to/test-export.py [static|shared] 9*baec84f2Syuangongji 10*baec84f2Syuangongjiimport sys 11*baec84f2Syuangongjiimport os 12*baec84f2Syuangongjiimport shutil 13*baec84f2Syuangongjiimport platform 14*baec84f2Syuangongjiimport subprocess 15*baec84f2Syuangongjiimport tempfile 16*baec84f2Syuangongji 17*baec84f2Syuangongjiresults = ("success", "failure") 18*baec84f2SyuangongjiFNULL = open(os.devnull, 'wb') 19*baec84f2Syuangongjiscript_dir = os.path.split(os.path.realpath(sys.argv[0]))[0] 20*baec84f2Syuangongji# working_dir is cmake build dir 21*baec84f2Syuangongjiworking_dir = os.getcwd() 22*baec84f2Syuangongjiif len(sys.argv) > 1 and sys.argv[1] == "static": 23*baec84f2Syuangongji link_type = sys.argv[1] 24*baec84f2Syuangongjielse: 25*baec84f2Syuangongji link_type = "shared" 26*baec84f2Syuangongji 27*baec84f2Syuangongji 28*baec84f2Syuangongjidef exec_cmd(cmd, silent): 29*baec84f2Syuangongji if silent: 30*baec84f2Syuangongji p = subprocess.Popen(cmd, stdout=FNULL, stderr=FNULL, shell=True) 31*baec84f2Syuangongji else: 32*baec84f2Syuangongji p = subprocess.Popen(cmd, shell=True) 33*baec84f2Syuangongji p.communicate() 34*baec84f2Syuangongji return p.poll() 35*baec84f2Syuangongji 36*baec84f2Syuangongji 37*baec84f2Syuangongjidef link_and_run(link, code): 38*baec84f2Syuangongji """Check if the source code matches the library component. 39*baec84f2Syuangongji 40*baec84f2Syuangongji Compile source code relative to one component and link to another component. 41*baec84f2Syuangongji Then run the generated executor. 42*baec84f2Syuangongji 43*baec84f2Syuangongji Args: 44*baec84f2Syuangongji link: The name of component that the source code will link with. 45*baec84f2Syuangongji code: The source code related component name. 46*baec84f2Syuangongji 47*baec84f2Syuangongji Returns: 48*baec84f2Syuangongji Returns 0 if links and runs successfully, otherwise 1. 49*baec84f2Syuangongji """ 50*baec84f2Syuangongji exec_cmd("cmake --build . --target clean", True) 51*baec84f2Syuangongji generator = '' 52*baec84f2Syuangongji if platform.system() == "Windows": 53*baec84f2Syuangongji generator = '-G "Visual Studio 15 2017 Win64"' 54*baec84f2Syuangongji cmd = 'cmake .. %s -DEVENT__LINK_COMPONENT=%s -DEVENT__CODE_COMPONENT=%s' % ( 55*baec84f2Syuangongji generator, link, code) 56*baec84f2Syuangongji if link_type == "static": 57*baec84f2Syuangongji cmd = "".join([cmd, " -DLIBEVENT_STATIC_LINK=1"]) 58*baec84f2Syuangongji r = exec_cmd(cmd, True) 59*baec84f2Syuangongji if r == 0: 60*baec84f2Syuangongji r = exec_cmd('cmake --build .', True) 61*baec84f2Syuangongji if r == 0: 62*baec84f2Syuangongji r = exec_cmd('ctest', True) 63*baec84f2Syuangongji if r != 0: 64*baec84f2Syuangongji r = 1 65*baec84f2Syuangongji return r 66*baec84f2Syuangongji 67*baec84f2Syuangongji# expect 0:success 1:failure 68*baec84f2Syuangongjidef testcase(link, code, expect): 69*baec84f2Syuangongji r = link_and_run(link, code) 70*baec84f2Syuangongji if link == "": 71*baec84f2Syuangongji link = "all" 72*baec84f2Syuangongji if code == "": 73*baec84f2Syuangongji code = "all" 74*baec84f2Syuangongji if r != expect: 75*baec84f2Syuangongji print('[test-export] fail: link %s and run %s expects %s but gets %s.' % 76*baec84f2Syuangongji (link, code, results[expect], results[r])) 77*baec84f2Syuangongji sys.exit(1) 78*baec84f2Syuangongji else: 79*baec84f2Syuangongji print('[test-export] success: link %s and run %s expects and gets %s.' % 80*baec84f2Syuangongji (link, code, results[r])) 81*baec84f2Syuangongji 82*baec84f2Syuangongji# Dependency relationships between libevent libraries: 83*baec84f2Syuangongji# core: none 84*baec84f2Syuangongji# extra: core 85*baec84f2Syuangongji# pthreads: core,pthread 86*baec84f2Syuangongji# openssl: core,openssl 87*baec84f2Syuangongjidef test_group(): 88*baec84f2Syuangongji testcase("core", "core", 0) 89*baec84f2Syuangongji testcase("extra", "extra", 0) 90*baec84f2Syuangongji testcase("openssl", "openssl", 0) 91*baec84f2Syuangongji testcase("", "", 0) 92*baec84f2Syuangongji testcase("extra", "core", 0) 93*baec84f2Syuangongji testcase("openssl", "core", 0) 94*baec84f2Syuangongji testcase("core", "extra", 1) 95*baec84f2Syuangongji testcase("core", "openssl", 1) 96*baec84f2Syuangongji testcase("extra", "openssl", 1) 97*baec84f2Syuangongji testcase("openssl", "extra", 1) 98*baec84f2Syuangongji if platform.system() != "Windows": 99*baec84f2Syuangongji testcase("pthreads", "pthreads", 0) 100*baec84f2Syuangongji testcase("pthreads", "core", 0) 101*baec84f2Syuangongji testcase("core", "pthreads", 1) 102*baec84f2Syuangongji testcase("extra", "pthreads", 1) 103*baec84f2Syuangongji testcase("pthreads", "extra", 1) 104*baec84f2Syuangongji testcase("pthreads", "openssl", 1) 105*baec84f2Syuangongji testcase("openssl", "pthreads", 1) 106*baec84f2Syuangongji 107*baec84f2Syuangongji 108*baec84f2Syuangongjidef config_restore(): 109*baec84f2Syuangongji if os.path.isfile("tempconfig") and not os.path.isfile("LibeventConfig.cmake"): 110*baec84f2Syuangongji os.rename("tempconfig", "LibeventConfig.cmake") 111*baec84f2Syuangongji 112*baec84f2Syuangongji 113*baec84f2Syuangongjidef config_backup(): 114*baec84f2Syuangongji if os.path.isfile("tempconfig"): 115*baec84f2Syuangongji os.remove("tempconfig") 116*baec84f2Syuangongji if os.path.isfile("LibeventConfig.cmake"): 117*baec84f2Syuangongji os.rename("LibeventConfig.cmake", "tempconfig") 118*baec84f2Syuangongji 119*baec84f2Syuangongji 120*baec84f2Syuangongjishutil.rmtree(os.path.join(script_dir, "build"), ignore_errors=True) 121*baec84f2Syuangongji 122*baec84f2Syuangongji 123*baec84f2Syuangongjidef run_test_group(): 124*baec84f2Syuangongji os.chdir(script_dir) 125*baec84f2Syuangongji if not os.path.isdir("build"): 126*baec84f2Syuangongji os.mkdir("build") 127*baec84f2Syuangongji os.chdir("build") 128*baec84f2Syuangongji test_group() 129*baec84f2Syuangongji os.chdir(working_dir) 130*baec84f2Syuangongji 131*baec84f2Syuangongji 132*baec84f2Syuangongjineed_exportdll = False 133*baec84f2Syuangongjiif link_type == "shared" and platform.system() == "Windows": 134*baec84f2Syuangongji need_exportdll = True 135*baec84f2Syuangongji 136*baec84f2Syuangongji# On Windows, we need to add the directory containing the dll to the 137*baec84f2Syuangongji# 'PATH' environment variable so that the program can call it. 138*baec84f2Syuangongjidef export_dll(dir): 139*baec84f2Syuangongji if need_exportdll: 140*baec84f2Syuangongji os.environ["PATH"] += os.pathsep + dir 141*baec84f2Syuangongji 142*baec84f2Syuangongji 143*baec84f2Syuangongjidef unexport_dll(dir): 144*baec84f2Syuangongji if need_exportdll: 145*baec84f2Syuangongji paths = os.environ["PATH"].split(os.pathsep) 146*baec84f2Syuangongji paths = list(set(paths)) 147*baec84f2Syuangongji if dir in paths: 148*baec84f2Syuangongji paths.remove(dir) 149*baec84f2Syuangongji os.environ["PATH"] = os.pathsep.join(paths) 150*baec84f2Syuangongji 151*baec84f2Syuangongji 152*baec84f2Syuangongjiprint("[test-export] use %s library" % link_type) 153*baec84f2Syuangongji 154*baec84f2Syuangongji# Test for build tree. 155*baec84f2Syuangongjiprint("[test-export] test for build tree") 156*baec84f2Syuangongjidllpath = os.path.join(working_dir, "bin", "Debug") 157*baec84f2Syuangongjiconfig_restore() 158*baec84f2Syuangongjios.environ["CMAKE_PREFIX_PATH"] = working_dir 159*baec84f2Syuangongjiexport_dll(dllpath) 160*baec84f2Syuangongjirun_test_group() 161*baec84f2Syuangongjidel os.environ["CMAKE_PREFIX_PATH"] 162*baec84f2Syuangongjiunexport_dll(dllpath) 163*baec84f2Syuangongji 164*baec84f2Syuangongji# Install libevent libraries to system path. Remove LibeventConfig.cmake 165*baec84f2Syuangongji# from build directory to avoid confusion when using find_package(). 166*baec84f2Syuangongjiprint("[test-export] test for install tree(in system-wide path)") 167*baec84f2Syuangongjiif platform.system() == "Windows": 168*baec84f2Syuangongji prefix = "C:\\Program Files\\libevent" 169*baec84f2Syuangongji dllpath = os.path.join(prefix, "lib") 170*baec84f2Syuangongjielse: 171*baec84f2Syuangongji prefix = "/usr/local" 172*baec84f2Syuangongjiexec_cmd('cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % prefix, True) 173*baec84f2Syuangongjiexec_cmd('cmake --build . --target install', True) 174*baec84f2Syuangongjiconfig_backup() 175*baec84f2Syuangongjios.environ["CMAKE_PREFIX_PATH"] = os.path.join(prefix, "lib/cmake/libevent") 176*baec84f2Syuangongjiexport_dll(dllpath) 177*baec84f2Syuangongjirun_test_group() 178*baec84f2Syuangongjiunexport_dll(dllpath) 179*baec84f2Syuangongjidel os.environ["CMAKE_PREFIX_PATH"] 180*baec84f2Syuangongji 181*baec84f2Syuangongji# Uninstall the libraries installed in the above steps. Install the libraries 182*baec84f2Syuangongji# into a temporary directory. Same as above, remove LibeventConfig.cmake from 183*baec84f2Syuangongji# build directory to avoid confusion when using find_package(). 184*baec84f2Syuangongjiprint("[test-export] test for install tree(in non-system-wide path)") 185*baec84f2Syuangongjiexec_cmd("cmake --build . --target uninstall", True) 186*baec84f2Syuangongjitempdir = tempfile.TemporaryDirectory() 187*baec84f2Syuangongjicmd = 'cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % tempdir.name 188*baec84f2Syuangongjiexec_cmd(cmd, True) 189*baec84f2Syuangongjiexec_cmd("cmake --build . --target install", True) 190*baec84f2Syuangongjiconfig_backup() 191*baec84f2Syuangongjios.environ["CMAKE_PREFIX_PATH"] = os.path.join(tempdir.name, "lib/cmake/libevent") 192*baec84f2Syuangongjidllpath = os.path.join(tempdir.name, "lib") 193*baec84f2Syuangongjiexport_dll(dllpath) 194*baec84f2Syuangongjirun_test_group() 195*baec84f2Syuangongjiunexport_dll(dllpath) 196*baec84f2Syuangongjidel os.environ["CMAKE_PREFIX_PATH"] 197*baec84f2Syuangongjiconfig_restore() 198*baec84f2Syuangongji 199*baec84f2Syuangongjiprint("[test-export] all testcases have run successfully") 200