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