From 44c441c43610aeed8ebeb5da82bbb36f5bbca378 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 10:36:22 +0200 Subject: [PATCH 01/55] Rename and move cue to top level --- appveyor/do.py => cue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename appveyor/do.py => cue.py (99%) diff --git a/appveyor/do.py b/cue.py similarity index 99% rename from appveyor/do.py rename to cue.py index 8887437..0fb32a4 100644 --- a/appveyor/do.py +++ b/cue.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -"""Windows (AppVeyor) ci build script +"""CI build script """ from __future__ import print_function From c3920bc499a670ccd5348b510d244a1faf57e621 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 14:01:50 +0200 Subject: [PATCH 02/55] Minimal set of builds on Travis --- .travis.yml | 132 ++++++---------------------------------------------- 1 file changed, 15 insertions(+), 117 deletions(-) diff --git a/.travis.yml b/.travis.yml index 535ec23..fd41258 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ cache: env: global: - SETUP_PATH=.:.ci + - VV=1 addons: apt: @@ -30,14 +31,13 @@ addons: homebrew: packages: - re2c - - bash update: true install: - - ./travis/prepare.sh + - python cue.py prepare script: - - ./travis-test.sh + - python cue.py build # If you need to do more during install and build, # add a local directory to your module and do e.g. @@ -62,120 +62,18 @@ script: jobs: include: + - env: SET=test01 + + - env: SET=test01 + os: windows + + - env: SET=test01 + compiler: vs2017 + os: windows + # Run unit tests on Linux and Mac - - env: SET=test00 +# - env: SET=test00 - - env: SET=test00 - os: osx - -# Compile the example application -# using the build configurations from full makeBaseApp example - - - env: SET=test01 - -# On the side: test ADD_MODULES - - env: SET=test01 ADD_MODULES=ipac - compiler: clang - - - env: VV="" SET=test01 - - - env: SET=test01 EXTRA="CMD_CXXFLAGS=-std=c++11" - - - env: SET=test01 EXTRA="CMD_CXXFLAGS=-std=c++11" - compiler: clang - -# trusty is pretty close to RHEL7 - - env: SET=test01 - dist: trusty - - - env: SET=test01 EXTRA="CMD_CXXFLAGS=-std=c++11" - dist: trusty - -# Cross-compilation to Windows using MinGW and WINE - - - env: SET=test01 WINE=32 TEST=NO STATIC=YES - compiler: mingw - - - env: SET=test01 WINE=64 TEST=NO STATIC=YES - compiler: mingw - -# dynamic (DLL) builds are broken on xenial - - env: SET=test01 WINE=32 TEST=NO STATIC=NO - dist: bionic - compiler: mingw - - - env: SET=test01 WINE=64 TEST=NO STATIC=NO - dist: bionic - compiler: mingw - -# Cross-compilation to RTEMS -# (needs EPICS Base >= 3.16.2) - - - env: SET=test01 RTEMS=4.10 - - - env: SET=test01 RTEMS=4.9 - -# Other gcc versions (adding as an extra package) - - - env: SET=test01 - compiler: gcc-6 - addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } } - - - env: SET=test01 - compiler: gcc-7 - addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } } - -# MacOS build - -# SNCSEQ 2.2.7 fails to build on MacOS; currently needs master - - env: SET=test01 SNCSEQ=master - os: osx - compiler: clang - -# Base 3.15 builds -# ================ - - - env: BASE=R3.15.7 SET=test01 - - - env: BASE=R3.15.7 SET=test01 WINE=64 TEST=NO STATIC=YES - dist: bionic - compiler: mingw - -# The DLL build for this Base version is known to fail -# - env: BASE=R3.15.7 SET=test01 WINE=64 TEST=NO STATIC=NO -# dist: bionic -# compiler: mingw - -# Cross-compilation to RTEMS -# (needs EPICS Base >= 3.16.2) - - - env: BASE=R3.16.2 SET=test01 RTEMS=4.10 - dist: trusty - - - env: BASE=R3.16.2 SET=test01 RTEMS=4.9 - dist: trusty - -# SNCSEQ 2.2.7 fails to build on MacOS; currently needs master - - env: BASE=R3.15.7 SET=test01 SNCSEQ=master - os: osx - compiler: clang - -# Base 3.14 builds -# ================ - - - env: BASE=R3.14.12.8 SET=test01 - - - env: BASE=R3.14.12.8 SET=test01 WINE=64 TEST=NO STATIC=YES - dist: bionic - compiler: mingw - -# The DLL build for this Base version is known to fail -# - env: BASE=R3.14.12.8 SET=test01 WINE=64 TEST=NO STATIC=NO -# dist: bionic -# compiler: mingw - -# SNCSEQ 2.2.7 fails to build on MacOS; currently needs master - - env: BASE=R3.14.12.8 SET=test01 SNCSEQ=master - os: osx - compiler: clang +# - env: SET=test00 +# os: osx From 488053cea462de741810cb47f9604a0be7aab7bf Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 12:34:04 +0200 Subject: [PATCH 03/55] cue: detect CI configuration and set up accordingly - configuration: static/shared, debug/optimized - compiler: gcc, mingw, vs.... - platform: x86/x64 - service and os: travis/appveyor, linux/windows/macos --- cue.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/cue.py b/cue.py index 0fb32a4..27912de 100644 --- a/cue.py +++ b/cue.py @@ -13,6 +13,56 @@ import distutils.util logger = logging.getLogger(__name__) +# Detect the service and set up environment accordingly + +ci_service = '' +ci_os = '' +ci_platform = '' +ci_compiler = '' +ci_static = False +ci_debug = False + +if 'TRAVIS' in os.environ: + ci_service = 'travis' + ci_os = os.environ['TRAVIS_OS_NAME'] + if ci_os == 'windows': + # Only Visual Studio 2017 available + ci_compiler = 'vs2017' + ci_platform = 'x64' + ci_compiler = os.environ['TRAVIS_COMPILER'] + if 'STATIC' in os.environ and os.environ['STATIC'].lower() == 'yes': + ci_static = True + if 'DEBUG' in os.environ and os.environ['DEBUG'].lower() == 'yes': + ci_debug = True + +if 'APPVEYOR' in os.environ: + ci_service = 'appveyor' + if re.match(r'^Visual', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'windows' + elif re.match(r'^Ubuntu', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'linux' + elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'osx' + ci_platform = os.environ['PLATFORM'].lower() + if 'CMP' in os.environ: + ci_compiler = os.environ['CMP'] + if re.search('static', os.environ['CONFIGURATION']): + ci_static = True + if re.search('debug', os.environ['CONFIGURATION']): + ci_debug = True + +if ci_static: + ci_configuration = 'static' +else: + ci_configuration = 'shared' +if ci_debug: + ci_configuration += '-debug' +else: + ci_configuration += '-optimized' + +logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', + ci_service, ci_compiler, ci_os, ci_platform, ci_configuration) + # Setup ANSI Colors ANSI_RED = "\033[31;1m" ANSI_GREEN = "\033[32;1m" @@ -82,8 +132,8 @@ has_test_results = False silent_dep_builds = True def host_info(): - print('{0}AppVeyor Build Worker Image:{1} {2}' - .format(ANSI_CYAN, ANSI_RESET, os.environ['APPVEYOR_BUILD_WORKER_IMAGE'])) + print('{0}Build using {1} compiler on {2} ({3}) hosted by {4}{5}' + .format(ANSI_CYAN, ci_compiler, ci_os, ci_platform, ci_service, ANSI_RESET)) print('{0}Python setup{1}'.format(ANSI_CYAN, ANSI_RESET)) print(sys.version) @@ -368,31 +418,31 @@ def setup_for_build(args): # so a combined debug and static target will appear to be just static # but debug will have been specified in CONFIG_SITE by prepare() hostarchsuffix='' - if re.search('debug', os.environ['CONFIGURATION']): + if ci_debug: hostarchsuffix = '-debug' - if re.search('static', os.environ['CONFIGURATION']): + if ci_static: hostarchsuffix = '-static' - if os.environ['PLATFORM'].lower() == 'x86': + if ci_platform == 'x86': os.environ['EPICS_HOST_ARCH'] = 'win32-x86' + hostarchsuffix - elif os.environ['PLATFORM'].lower() == 'x64': + elif ci_platform == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix - if os.environ['CMP'] == 'vs2019': + if ci_compiler == 'vs2019': # put strawberry perl in the PATH os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), os.path.join(r'C:\Strawberry\perl\bin'), os.environ['PATH']]) - if os.environ['CMP'] == 'mingw': + if ci_compiler == 'mingw': if 'INCLUDE' not in os.environ: os.environ['INCLUDE'] = '' - if os.environ['PLATFORM'].lower() == 'x86': + if ci_platform == 'x86': os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', os.environ['PATH']]) - elif os.environ['PLATFORM'].lower() == 'x64': + elif ci_platform == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', os.environ['INCLUDE']]) @@ -480,13 +530,13 @@ def prepare(args): print('{0}Configuring EPICS build system{1}'.format(ANSI_YELLOW, ANSI_RESET)) with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as config_site: - if re.search('static', os.environ['CONFIGURATION']): + if ci_static: config_site.write('SHARED_LIBRARIES=NO\n') config_site.write('STATIC_BUILD=YES\n') linktype = 'static' else: linktype = 'dynamic (DLL)' - if re.search('debug', os.environ['CONFIGURATION']): + if ci_debug: config_site.write('HOST_OPT=NO\n') optitype = 'debug' else: @@ -541,7 +591,7 @@ endif''') sys.stdout.flush() sp.check_call(['perl', '--version']) - if os.environ['CMP'] == 'mingw': + if ci_compiler == 'mingw': print('{0}$ gcc --version{1}'.format(ANSI_CYAN, ANSI_RESET)) sys.stdout.flush() sp.check_call(['gcc', '--version']) @@ -592,7 +642,7 @@ def doExec(args): def with_vcvars(cmd): '''re-exec main script with a (hopefully different) command ''' - CC = os.environ['CMP'] + CC = ci_compiler # cf. https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line @@ -605,7 +655,7 @@ def with_vcvars(cmd): info['arch'] = { 'x86': 'x86', # 'amd64_x86' ?? 'x64': 'amd64', - }[os.environ['PLATFORM'].lower()] # 'x86' or 'x64' + }[ci_platform] # 'x86' or 'x64' info['vcvars'] = vcvars_table[CC] @@ -624,7 +674,7 @@ call "{vcvars}" {arch} F.write(script) print('{0}Calling vcvars-trampoline.bat to set environment for {1} on {2}{3}' - .format(ANSI_YELLOW, CC, os.environ['PLATFORM'], ANSI_RESET)) + .format(ANSI_YELLOW, CC, ci_platform, ANSI_RESET)) sys.stdout.flush() returncode = sp.call('vcvars-trampoline.bat', shell=True) if returncode != 0: @@ -662,7 +712,7 @@ def main(raw): logging.basicConfig(level=logging.DEBUG) silent_dep_builds = False - if args.vcvars and os.environ['CMP'].startswith('vs'): + if args.vcvars and ci_compiler.startswith('vs'): # re-exec with MSVC in PATH with_vcvars(' '.join(['--no-vcvars']+raw)) From 044ff8fa88b4a65afc9268509de67112908c764d Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 16:10:53 +0200 Subject: [PATCH 04/55] cue: use 'gcc' for native MinGW on Windows --- cue.py | 62 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/cue.py b/cue.py index 27912de..a7503c3 100644 --- a/cue.py +++ b/cue.py @@ -428,28 +428,29 @@ def setup_for_build(args): elif ci_platform == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix - if ci_compiler == 'vs2019': - # put strawberry perl in the PATH - os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), - os.path.join(r'C:\Strawberry\perl\bin'), - os.environ['PATH']]) - if ci_compiler == 'mingw': - if 'INCLUDE' not in os.environ: - os.environ['INCLUDE'] = '' - if ci_platform == 'x86': - os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', - os.environ['INCLUDE']]) - os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', - os.environ['PATH']]) - elif ci_platform == 'x64': - os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', - os.environ['INCLUDE']]) - os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', + if ci_service == 'appveyor' and ci_os == 'windows': + if ci_compiler == 'vs2019': + # put strawberry perl in the PATH + os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), + os.path.join(r'C:\Strawberry\perl\bin'), os.environ['PATH']]) + if ci_compiler == 'gcc': + if 'INCLUDE' not in os.environ: + os.environ['INCLUDE'] = '' + if ci_platform == 'x86': + os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' + os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', + os.environ['INCLUDE']]) + os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', + os.environ['PATH']]) + elif ci_platform == 'x64': + os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' + os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', + os.environ['INCLUDE']]) + os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', + os.environ['PATH']]) - make = os.path.join(toolsdir, 'make.exe') + make = os.path.join(toolsdir, 'make.exe') base_place = '.' if not building_base: @@ -571,15 +572,16 @@ endif''') if not os.path.isdir(toolsdir): os.makedirs(toolsdir) - makever = '4.2.1' - if not os.path.exists(os.path.join(toolsdir, 'make.exe')): - print('Installing Make 4.2.1 from ANL web site') - sys.stdout.flush() - sp.check_call(['curl', '-fsS', '--retry', '3', '-o', 'make-{0}.zip'.format(makever), - 'https://epics.anl.gov/download/tools/make-{0}-win64.zip'.format(makever)], - cwd=toolsdir) - sp.check_call([zip7, 'e', 'make-{0}.zip'.format(makever)], cwd=toolsdir) - os.remove(os.path.join(toolsdir, 'make-{0}.zip'.format(makever))) + if ci_os == 'windows': + makever = '4.2.1' + if not os.path.exists(os.path.join(toolsdir, 'make.exe')): + print('Installing Make 4.2.1 from ANL web site') + sys.stdout.flush() + sp.check_call(['curl', '-fsS', '--retry', '3', '-o', 'make-{0}.zip'.format(makever), + 'https://epics.anl.gov/download/tools/make-{0}-win64.zip'.format(makever)], + cwd=toolsdir) + sp.check_call([zip7, 'e', 'make-{0}.zip'.format(makever)], cwd=toolsdir) + os.remove(os.path.join(toolsdir, 'make-{0}.zip'.format(makever))) setup_for_build(args) @@ -591,7 +593,7 @@ endif''') sys.stdout.flush() sp.check_call(['perl', '--version']) - if ci_compiler == 'mingw': + if ci_compiler == 'gcc': print('{0}$ gcc --version{1}'.format(ANSI_CYAN, ANSI_RESET)) sys.stdout.flush() sp.check_call(['gcc', '--version']) From 91aba0df5c082b34b00e5088c98c7845de70cb3e Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 16:16:42 +0200 Subject: [PATCH 05/55] cue: assume 'make' in PATH by default --- cue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cue.py b/cue.py index a7503c3..d76309b 100644 --- a/cue.py +++ b/cue.py @@ -126,7 +126,7 @@ def modlist(): return ret zip7 = r'C:\Program Files\7-Zip\7z' -make = '' +make = 'make' isbase314 = False has_test_results = False silent_dep_builds = True From 98cf1e709f15922cb750fe02fa1eab42d3a36517 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 16:33:26 +0200 Subject: [PATCH 06/55] cue: fix Windows setup_for_build() --- cue.py | 85 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/cue.py b/cue.py index d76309b..1777ec9 100644 --- a/cue.py +++ b/cue.py @@ -414,44 +414,51 @@ def setup_for_build(args): global make, isbase314, has_test_results dllpaths = [] - # there is no combined static and debug EPICS_HOST_ARCH target, - # so a combined debug and static target will appear to be just static - # but debug will have been specified in CONFIG_SITE by prepare() - hostarchsuffix='' - if ci_debug: - hostarchsuffix = '-debug' - if ci_static: - hostarchsuffix = '-static' - - if ci_platform == 'x86': - os.environ['EPICS_HOST_ARCH'] = 'win32-x86' + hostarchsuffix - elif ci_platform == 'x64': - os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix - - if ci_service == 'appveyor' and ci_os == 'windows': - if ci_compiler == 'vs2019': - # put strawberry perl in the PATH - os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), - os.path.join(r'C:\Strawberry\perl\bin'), - os.environ['PATH']]) - if ci_compiler == 'gcc': - if 'INCLUDE' not in os.environ: - os.environ['INCLUDE'] = '' - if ci_platform == 'x86': - os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', - os.environ['INCLUDE']]) - os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', - os.environ['PATH']]) - elif ci_platform == 'x64': - os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', - os.environ['INCLUDE']]) - os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', - os.environ['PATH']]) - + if ci_os == 'windows': make = os.path.join(toolsdir, 'make.exe') + if re.match(r'^vs', ci_compiler): + # there is no combined static and debug EPICS_HOST_ARCH target, + # so a combined debug and static target will appear to be just static + # but debug will have been specified in CONFIG_SITE by prepare() + hostarchsuffix = '' + if ci_debug: + hostarchsuffix = '-debug' + if ci_static: + hostarchsuffix = '-static' + + if ci_platform == 'x86': + os.environ['EPICS_HOST_ARCH'] = 'win32-x86' + hostarchsuffix + elif ci_platform == 'x64': + os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix + + if ci_service == 'appveyor': + if ci_compiler == 'vs2019': + # put strawberry perl in the PATH + os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), + os.path.join(r'C:\Strawberry\perl\bin'), + os.environ['PATH']]) + if ci_compiler == 'gcc': + if 'INCLUDE' not in os.environ: + os.environ['INCLUDE'] = '' + if ci_platform == 'x86': + os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' + os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', + os.environ['INCLUDE']]) + os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', + os.environ['PATH']]) + elif ci_platform == 'x64': + os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' + os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', + os.environ['INCLUDE']]) + os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', + os.environ['PATH']]) + # Add DLL location to PATH + bindir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) + if os.path.isdir(bindir): + dllpaths.append(bindir) + os.environ['PATH'] = os.pathsep.join(dllpaths + [os.environ['PATH']]) + base_place = '.' if not building_base: with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: @@ -478,12 +485,6 @@ def setup_for_build(args): if re.match('^test-results:', line): has_test_results = True - bindir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) - if os.path.isdir(bindir): - dllpaths.append(bindir) - - os.environ['PATH'] = os.pathsep.join(dllpaths + [os.environ['PATH']]) - # apparently %CD% is handled automagically os.environ['TOP'] = os.getcwd() From 5106e1d75344694abc05de4731ab787dc894755f Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 17:57:44 +0200 Subject: [PATCH 07/55] cue: add call to epicsHostArch.pl script --- cue.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cue.py b/cue.py index 1777ec9..a7668ad 100644 --- a/cue.py +++ b/cue.py @@ -471,6 +471,17 @@ def setup_for_build(args): if mod == 'EPICS_BASE': base_place = place + if 'EPICS_HOST_ARCH' not in os.environ: + os.environ['EPICS_HOST_ARCH'] = 'unknown' + eha_scripts = [ + os.pathsep.join(base_place, 'src', 'tools', 'EpicsHostArch.pl'), + os.pathsep.join(base_place, 'startup', 'EpicsHostArch.pl'), + ] + for eha in eha_scripts: + if os.path.exists(eha): + os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]) + break + cfg_base_version = os.path.join(base_place, 'configure', 'CONFIG_BASE_VERSION') if os.path.exists(cfg_base_version): with open(cfg_base_version) as myfile: From 7d9b5985c68f9410b1609fb811d772e7216ccc11 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 May 2020 18:18:25 +0200 Subject: [PATCH 08/55] cue: fix setting EPICS_BASE and EPICS_HOST_ARCH --- cue.py | 105 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/cue.py b/cue.py index a7668ad..4c67211 100644 --- a/cue.py +++ b/cue.py @@ -63,6 +63,20 @@ else: logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', ci_service, ci_compiler, ci_os, ci_platform, ci_configuration) +curdir = os.getcwd() +ci_scriptsdir = os.path.abspath(os.path.dirname(sys.argv[0])) + +seen_setups = [] +modules_to_compile = [] +setup = {} +places = {} + +if 'BASE' in os.environ and os.environ['BASE'] == 'SELF': + building_base = True + places['EPICS_BASE'] = curdir +else: + building_base = False + # Setup ANSI Colors ANSI_RED = "\033[31;1m" ANSI_GREEN = "\033[32;1m" @@ -73,11 +87,6 @@ ANSI_CYAN = "\033[36;1m" ANSI_RESET = "\033[0m" ANSI_CLEAR = "\033[0K" -seen_setups = [] -modules_to_compile = [] -setup = {} -places = {} - if 'HomeDrive' in os.environ: cachedir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.cache') toolsdir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.tools') @@ -102,16 +111,6 @@ vcvars_table = { 'vs2008':r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat', } -ciscriptsdir = os.path.abspath(os.path.dirname(sys.argv[0])) -if os.path.basename(ciscriptsdir) == 'appveyor': - ciscriptsdir = ciscriptsdir.rstrip(os.pathsep+'appveyor') - -if 'BASE' in os.environ and os.environ['BASE'] == 'SELF': - building_base = True - places['EPICS_BASE'] = '.' -else: - building_base = False - def modlist(): if building_base: ret = [] @@ -384,7 +383,7 @@ def add_dependency(dep): if 'BASE_3_14=YES' in f.read(): print('Adding MSI 1.7 to {0}'.format(place)) sys.stdout.flush() - sp.check_call(['patch', '-p1', '-i', os.path.join(ciscriptsdir, 'add-msi-to-314.patch')], + sp.check_call(['patch', '-p1', '-i', os.path.join(ci_scriptsdir, 'add-msi-to-314.patch')], cwd=place) else: # force including RELEASE.local for non-base modules by overwriting their configure/RELEASE @@ -442,54 +441,68 @@ def setup_for_build(args): if 'INCLUDE' not in os.environ: os.environ['INCLUDE'] = '' if ci_platform == 'x86': - os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', os.environ['PATH']]) elif ci_platform == 'x64': - os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', os.environ['PATH']]) - # Add DLL location to PATH - bindir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) - if os.path.isdir(bindir): - dllpaths.append(bindir) - os.environ['PATH'] = os.pathsep.join(dllpaths + [os.environ['PATH']]) + if ci_compiler == 'gcc': + if ci_platform == 'x86': + os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' + elif ci_platform == 'x64': + os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' - base_place = '.' + # Find BASE location if not building_base: with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: lines = f.readlines() for line in lines: (mod, place) = line.strip().split('=') - bindir = os.path.join(place, 'bin', os.environ['EPICS_HOST_ARCH']) - if os.path.isdir(bindir): - dllpaths.append(bindir) if mod == 'EPICS_BASE': - base_place = place + places['EPICS_BASE'] = place if 'EPICS_HOST_ARCH' not in os.environ: + logger.debug('Detecting EPICS host architecture in %s', places['EPICS_BASE']) os.environ['EPICS_HOST_ARCH'] = 'unknown' eha_scripts = [ - os.pathsep.join(base_place, 'src', 'tools', 'EpicsHostArch.pl'), - os.pathsep.join(base_place, 'startup', 'EpicsHostArch.pl'), + os.path.join(places['EPICS_BASE'], 'src', 'tools', 'EpicsHostArch.pl'), + os.path.join(places['EPICS_BASE'], 'startup', 'EpicsHostArch.pl'), ] for eha in eha_scripts: if os.path.exists(eha): - os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]) + os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]).strip() + logger.debug('%s returned: %s', + eha, os.environ['EPICS_HOST_ARCH']) break - cfg_base_version = os.path.join(base_place, 'configure', 'CONFIG_BASE_VERSION') + if ci_os == 'windows': + if not building_base: + with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: + lines = f.readlines() + for line in lines: + (mod, place) = line.strip().split('=') + bindir = os.path.join(place, 'bin', os.environ['EPICS_HOST_ARCH']) + if os.path.isdir(bindir): + dllpaths.append(bindir) + # Add DLL location to PATH + bindir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) + if os.path.isdir(bindir): + dllpaths.append(bindir) + os.environ['PATH'] = os.pathsep.join(dllpaths + [os.environ['PATH']]) + logger.debug('DLL paths added to PATH: %s', os.pathsep.join(dllpaths)) + + cfg_base_version = os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_BASE_VERSION') if os.path.exists(cfg_base_version): with open(cfg_base_version) as myfile: if 'BASE_3_14=YES' in myfile.read(): isbase314 = True if not isbase314: - rules_build = os.path.join(base_place, 'configure', 'RULES_BUILD') + rules_build = os.path.join(places['EPICS_BASE'], 'configure', 'RULES_BUILD') if os.path.exists(rules_build): with open(rules_build) as myfile: for line in myfile: @@ -555,16 +568,18 @@ def prepare(args): else: optitype = 'optimized' - # Enable/fix parallel build for VisualStudio compiler on older Base versions - add_vs_fix = True - config_win = os.path.join(places['EPICS_BASE'], 'configure', 'os', 'CONFIG.win32-x86.win32-x86') - with open(config_win) as myfile: - for line in myfile: - if re.match(r'^ifneq \(\$\(VisualStudioVersion\),11\.0\)', line): - add_vs_fix = False - if add_vs_fix: - with open(config_win, 'a') as myfile: - myfile.write(''' + if ci_os == 'windows' and re.match(r'^vs', ci_compiler): + # Enable/fix parallel build for VisualStudio compiler on older Base versions + add_vs_fix = True + config_win = os.path.join(places['EPICS_BASE'], 'configure', 'os', 'CONFIG.win32-x86.win32-x86') + with open(config_win) as myfile: + for line in myfile: + if re.match(r'^ifneq \(\$\(VisualStudioVersion\),11\.0\)', line): + add_vs_fix = False + if add_vs_fix: + logger.debug('Adding parallel build fix for VisualStudio to %s', config_win) + with open(config_win, 'a') as myfile: + myfile.write(''' # Fix parallel build for some VisualStudio versions ifneq ($(VisualStudioVersion),) ifneq ($(VisualStudioVersion),11.0) @@ -576,8 +591,8 @@ else OPT_CXXFLAGS_NO := $(filter-out -FS,$(OPT_CXXFLAGS_NO)) OPT_CFLAGS_NO := $(filter-out -FS,$(OPT_CFLAGS_NO)) endif -endif''') - +endif''' + ) print('EPICS Base build system set up for {0} build with {1} linking' .format(optitype, linktype)) From e1a52130a7be9bf876df29a3ba83b9700ffc20c3 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 28 May 2020 14:29:10 +0200 Subject: [PATCH 09/55] cue: improve logging --- cue.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cue.py b/cue.py index 4c67211..a5f62db 100644 --- a/cue.py +++ b/cue.py @@ -181,23 +181,23 @@ def source_set(name): if os.path.isfile(set_file): seen_setups.append(set_file) - print("Loading setup file {0}".format(set_file)) + print("Opening setup file {0}".format(set_file)) sys.stdout.flush() with open(set_file) as fp: for line in fp: - logger.debug('Next line: %s', line.strip()) if not line.strip() or line.strip()[0] == '#': continue if line.startswith("include"): - logger.debug('Found an include, reading %s', line.split()[1]) + logger.debug('%s: Found include directive, reading %s next', + set_file, line.split()[1]) source_set(line.split()[1]) continue assign = line.replace('"', '').strip().split("=", 1) - logger.debug('Interpreting as assignment') setup.setdefault(assign[0], os.getenv(assign[0], "")) if not setup[assign[0]].strip(): - logger.debug('Doing assignment: %s = %s', assign[0], assign[1]) + logger.debug('%s: setup[%s] = %s', set_file, assign[0], assign[1]) setup[assign[0]] = assign[1] + logger.debug('Done with setup file %s', set_file) break else: raise NameError("{0}Setup file {1} does not exist in SETUP_PATH search path ({2}){3}" From b7d282fe3b92c6d3bbf48d203644ac3073163609 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 28 May 2020 15:06:15 +0200 Subject: [PATCH 10/55] cue: load 'defaults' setup file last --- cue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cue.py b/cue.py index a5f62db..e8f00e8 100644 --- a/cue.py +++ b/cue.py @@ -527,9 +527,9 @@ def prepare(args): host_info() print('{0}Loading setup files{1}'.format(ANSI_YELLOW, ANSI_RESET)) - source_set('defaults') if 'SET' in os.environ: source_set(os.environ['SET']) + source_set('defaults') [complete_setup(mod) for mod in modlist()] From 25517c35d13eae704e2b51e7556cedd3b74668d1 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 2 Jun 2020 14:30:52 +0200 Subject: [PATCH 11/55] windows: CHOCO for additional chocolatey packages Install: - make - @travis: strawberryperl the pre-installed perl does not have cpan and misses essentials like ExtUtils::Command - packages from CHOCO env --- .travis.yml | 1 + cue.py | 39 ++++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index fd41258..eeee272 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ env: global: - SETUP_PATH=.:.ci - VV=1 + - CHOCO=re2c addons: apt: diff --git a/cue.py b/cue.py index e8f00e8..2c7e687 100644 --- a/cue.py +++ b/cue.py @@ -21,15 +21,18 @@ ci_platform = '' ci_compiler = '' ci_static = False ci_debug = False +ci_choco = ['make'] if 'TRAVIS' in os.environ: ci_service = 'travis' ci_os = os.environ['TRAVIS_OS_NAME'] - if ci_os == 'windows': - # Only Visual Studio 2017 available - ci_compiler = 'vs2017' ci_platform = 'x64' ci_compiler = os.environ['TRAVIS_COMPILER'] + if ci_os == 'windows': + ci_choco.append('strawberryperl') + if re.match(r'^vs', ci_compiler): + # Only Visual Studio 2017 available + ci_compiler = 'vs2017' if 'STATIC' in os.environ and os.environ['STATIC'].lower() == 'yes': ci_static = True if 'DEBUG' in os.environ and os.environ['DEBUG'].lower() == 'yes': @@ -77,6 +80,9 @@ if 'BASE' in os.environ and os.environ['BASE'] == 'SELF': else: building_base = False +if 'CHOCO' in os.environ: + ci_choco.extend(os.environ['CHOCO'].split()) + # Setup ANSI Colors ANSI_RED = "\033[31;1m" ANSI_GREEN = "\033[32;1m" @@ -124,8 +130,6 @@ def modlist(): logger.debug('Effective module list: %s', ret) return ret -zip7 = r'C:\Program Files\7-Zip\7z' -make = 'make' isbase314 = False has_test_results = False silent_dep_builds = True @@ -278,9 +282,9 @@ def call_make(args=[], **kws): makeargs = ['-j{0}'.format(parallel), '-Otarget'] if silent: makeargs += ['-s'] - logger.debug("EXEC '%s' in %s", ' '.join([make] + makeargs + args), place) + logger.debug("EXEC '%s' in %s", ' '.join(['make'] + makeargs + args), place) sys.stdout.flush() - exitcode = sp.call([make] + makeargs + args, **kws) + exitcode = sp.call(['make'] + makeargs + args, **kws) logger.debug('EXEC DONE') if exitcode != 0: sys.exit(exitcode) @@ -414,8 +418,6 @@ def setup_for_build(args): dllpaths = [] if ci_os == 'windows': - make = os.path.join(toolsdir, 'make.exe') - if re.match(r'^vs', ci_compiler): # there is no combined static and debug EPICS_HOST_ARCH target, # so a combined debug and static target will appear to be just static @@ -450,6 +452,10 @@ def setup_for_build(args): os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', os.environ['PATH']]) + if ci_service == 'travis': + os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\perl\site\bin', r'C:\Strawberry\perl\bin', + os.environ['PATH']]) + if ci_compiler == 'gcc': if ci_platform == 'x86': os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' @@ -600,20 +606,15 @@ endif''' os.makedirs(toolsdir) if ci_os == 'windows': - makever = '4.2.1' - if not os.path.exists(os.path.join(toolsdir, 'make.exe')): - print('Installing Make 4.2.1 from ANL web site') + if ci_choco: + print('Installing chocolatey packages: {0}'.format(ci_choco)) sys.stdout.flush() - sp.check_call(['curl', '-fsS', '--retry', '3', '-o', 'make-{0}.zip'.format(makever), - 'https://epics.anl.gov/download/tools/make-{0}-win64.zip'.format(makever)], - cwd=toolsdir) - sp.check_call([zip7, 'e', 'make-{0}.zip'.format(makever)], cwd=toolsdir) - os.remove(os.path.join(toolsdir, 'make-{0}.zip'.format(makever))) + sp.check_call(['choco', 'install'] + ci_choco) setup_for_build(args) print('{0}EPICS_HOST_ARCH = {1}{2}'.format(ANSI_CYAN, os.environ['EPICS_HOST_ARCH'], ANSI_RESET)) - print('{0}$ {1} --version{2}'.format(ANSI_CYAN, make, ANSI_RESET)) + print('{0}$ make --version{1}'.format(ANSI_CYAN, ANSI_RESET)) sys.stdout.flush() call_make(['--version'], parallel=0) print('{0}$ perl --version{1}'.format(ANSI_CYAN, ANSI_RESET)) @@ -663,7 +664,7 @@ def test(args): def doExec(args): 'exec user command with vcvars' setup_for_build(args) - os.environ['MAKE'] = make + os.environ['MAKE'] = 'make' print('Execute command {}'.format(args.cmd)) sys.stdout.flush() sp.check_call(' '.join(args.cmd), shell=True) From 9f6995c4410e44c14719af0c2af2042af00139b1 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 28 May 2020 17:21:37 +0200 Subject: [PATCH 12/55] cue: allow multiple possible locations for a VS compiler version --- cue.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/cue.py b/cue.py index 2c7e687..9bd57f3 100644 --- a/cue.py +++ b/cue.py @@ -108,15 +108,22 @@ if 'CACHEDIR' in os.environ: vcvars_table = { # https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History - 'vs2019':r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat', - 'vs2017':r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat', - 'vs2015':r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat', - 'vs2013':r'C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat', - 'vs2012':r'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat', - 'vs2010':r'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat', - 'vs2008':r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat', + 'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'], + 'vs2017': [r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat', + r'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat'], + 'vs2015': [r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat'], + 'vs2013': [r'C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat'], + 'vs2012': [r'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat'], + 'vs2010': [r'C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat'], + 'vs2008': [r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat'], } +vcvars_found = {} +for key in vcvars_table: + for dir in vcvars_table[key]: + if os.path.exists(dir): + vcvars_found[key] = dir + def modlist(): if building_base: ret = [] @@ -146,9 +153,8 @@ def host_info(): print('platform =', distutils.util.get_platform()) print('{0}Available Visual Studio versions{1}'.format(ANSI_CYAN, ANSI_RESET)) - for key in vcvars_table: - if os.path.exists(vcvars_table[key]): - print('Found', key, 'in', vcvars_table[key]) + for key in vcvars_found: + print(key, 'in', vcvars_found[key]) sys.stdout.flush() # Used from unittests @@ -687,7 +693,7 @@ def with_vcvars(cmd): 'x64': 'amd64', }[ci_platform] # 'x86' or 'x64' - info['vcvars'] = vcvars_table[CC] + info['vcvars'] = vcvars_found[CC] script=''' call "{vcvars}" {arch} From bb5c73ae08839a940b5e492f51a0de774c62963d Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 28 May 2020 18:18:36 +0200 Subject: [PATCH 13/55] travis: BCFG for build configuration (static/debug) --- cue.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cue.py b/cue.py index 9bd57f3..fc53469 100644 --- a/cue.py +++ b/cue.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -"""CI build script +"""CI build script for Linux/MacOS/Windows on Travis/AppVeyor """ from __future__ import print_function @@ -33,10 +33,11 @@ if 'TRAVIS' in os.environ: if re.match(r'^vs', ci_compiler): # Only Visual Studio 2017 available ci_compiler = 'vs2017' - if 'STATIC' in os.environ and os.environ['STATIC'].lower() == 'yes': - ci_static = True - if 'DEBUG' in os.environ and os.environ['DEBUG'].lower() == 'yes': - ci_debug = True + if 'BCFG' in os.environ: + if re.search('static', os.environ['BCFG']): + ci_static = True + if re.search('debug', os.environ['BCFG']): + ci_debug = True if 'APPVEYOR' in os.environ: ci_service = 'appveyor' From 9bd635d058ca0446c4509b8075b4b461298e67a7 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 30 May 2020 14:41:32 +0200 Subject: [PATCH 14/55] Switch example to use sequencer R2.2.8 --- test01.set | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test01.set b/test01.set index 0260e61..2583e99 100644 --- a/test01.set +++ b/test01.set @@ -1,4 +1,4 @@ MODULES="sncseq" BASE=7.0 -SNCSEQ=R2-2-7 +SNCSEQ=R2-2-8 From 03d1a5456a8346fa436a2f94274c2cb59110a387 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sun, 31 May 2020 11:32:22 +0200 Subject: [PATCH 15/55] travis: add static/debug/static-debug builds --- .travis.yml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index eeee272..7776b92 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,16 +65,36 @@ jobs: - env: SET=test01 + - env: SET=test01 BCFG=static + + - env: SET=test01 BCFG=debug + + - env: SET=test01 BCFG=static-debug + - env: SET=test01 os: windows + - env: SET=test01 BCFG=static + os: windows + + - env: SET=test01 BCFG=debug + os: windows + + - env: SET=test01 BCFG=static-debug + os: windows + - env: SET=test01 compiler: vs2017 os: windows -# Run unit tests on Linux and Mac + - env: SET=test01 BCFG=static + compiler: vs2017 + os: windows -# - env: SET=test00 + - env: SET=test01 BCFG=debug + compiler: vs2017 + os: windows -# - env: SET=test00 -# os: osx + - env: SET=test01 BCFG=static-debug + compiler: vs2017 + os: windows From 28ef822dd50aee3609031acbfba6c73eb003d115 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 14:39:52 +0200 Subject: [PATCH 16/55] cue: add Travis fold control and AppVeyor printed folds fixes #42 --- cue.py | 66 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/cue.py b/cue.py index fc53469..0eea319 100644 --- a/cue.py +++ b/cue.py @@ -94,6 +94,27 @@ ANSI_CYAN = "\033[36;1m" ANSI_RESET = "\033[0m" ANSI_CLEAR = "\033[0K" +# Travis log fold control +# from https://github.com/travis-ci/travis-rubies/blob/build/build.sh + +def fold_start(tag, title): + if ci_service == 'travis': + print('travis_fold:start:{0}{1}{2}{3}' + .format(tag, ANSI_YELLOW, title, ANSI_RESET)) + elif ci['service'] == 'appveyor': + print('{0}===== \\/ \\/ \\/ ===== START: {1} ====={2}' + .format(ANSI_YELLOW, title, ANSI_RESET)) + sys.stdout.flush() + +def fold_end(tag, title): + if ci_service == 'travis': + print('\ntravis_fold:end:{0}\r' + .format(tag), end='') + elif ci_service == 'appveyor': + print('{0}----- /\\ /\\ /\\ ----- END: {1} -----{2}' + .format(ANSI_YELLOW, title, ANSI_RESET)) + sys.stdout.flush() + if 'HomeDrive' in os.environ: cachedir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.cache') toolsdir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.tools') @@ -135,7 +156,6 @@ def modlist(): setup[var] = os.environ[var] logger.debug('ENV assignment: %s = %s', var, setup[var]) ret = ['BASE'] + setup['ADD_MODULES'].upper().split() + setup['MODULES'].upper().split() - logger.debug('Effective module list: %s', ret) return ret isbase314 = False @@ -539,23 +559,27 @@ def setup_for_build(args): def prepare(args): host_info() - print('{0}Loading setup files{1}'.format(ANSI_YELLOW, ANSI_RESET)) + fold_start('load.setup', 'Loading setup files') + if 'SET' in os.environ: source_set(os.environ['SET']) source_set('defaults') [complete_setup(mod) for mod in modlist()] + fold_end('load.setup', 'Loading setup files') + logger.debug('Loaded setup') kvs = list(setup.items()) kvs.sort() [logger.debug(' %s = "%s"', *kv) for kv in kvs] + logger.debug('Effective module list: %s', ret) + # we're working with tags (detached heads) a lot: suppress advice call_git(['config', '--global', 'advice.detachedHead', 'false']) - print('{0}Checking/cloning dependencies{1}'.format(ANSI_YELLOW, ANSI_RESET)) - sys.stdout.flush() + fold_start('check.out.dependencies', 'Checking/cloning dependencies') [add_dependency(mod) for mod in modlist()] @@ -566,7 +590,9 @@ def prepare(args): targetdir = '.' shutil.copy(os.path.join(cachedir, 'RELEASE.local'), targetdir) - print('{0}Configuring EPICS build system{1}'.format(ANSI_YELLOW, ANSI_RESET)) + fold_end('check.out.dependencies', 'Checking/cloning dependencies') + + fold_start('set.up.epics_build', 'Configuring EPICS build system') with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as config_site: if ci_static: @@ -606,17 +632,19 @@ else endif endif''' ) + print('EPICS Base build system set up for {0} build with {1} linking' .format(optitype, linktype)) + fold_end('set.up.epics_build', 'Configuring EPICS build system') + if not os.path.isdir(toolsdir): os.makedirs(toolsdir) - if ci_os == 'windows': - if ci_choco: - print('Installing chocolatey packages: {0}'.format(ci_choco)) - sys.stdout.flush() - sp.check_call(['choco', 'install'] + ci_choco) + if ci_os == 'windows' and ci_choco: + fold_start('install.choco', 'Installing CHOCO packages') + sp.check_call(['choco', 'install'] + ci_choco) + fold_end('install.choco', 'Installing CHOCO packages') setup_for_build(args) @@ -638,10 +666,12 @@ endif''' sp.check_call(['cl']) if not building_base: + fold_start('build.dependencies', 'Build missing/outdated dependencies') for mod in modlist(): place = places[setup[mod+"_VARNAME"]] print('{0}Building dependency {1} in {2}{3}'.format(ANSI_YELLOW, mod, place, ANSI_RESET)) call_make(cwd=place, silent=silent_dep_builds) + fold_end('build.dependencies', 'Build missing/outdated dependencies') print('{0}Dependency module information{1}'.format(ANSI_CYAN, ANSI_RESET)) print('Module Tag Binaries Commit') @@ -656,25 +686,28 @@ endif''' def build(args): setup_for_build(args) - print('{0}Building the main module{1}'.format(ANSI_YELLOW, ANSI_RESET)) + fold_start('build.module', 'Build the main module') call_make(args.makeargs) + fold_end('build.module', 'Build the main module') def test(args): setup_for_build(args) + fold_start('test.module', 'Run the main module tests') print('{0}Running the main module tests{1}'.format(ANSI_YELLOW, ANSI_RESET)) if has_test_results: call_make(['tapfiles']) call_make(['test-results'], parallel=0, silent=True) else: call_make(['runtests']) + fold_end('test.module', 'Run the main module tests') def doExec(args): 'exec user command with vcvars' setup_for_build(args) os.environ['MAKE'] = 'make' - print('Execute command {}'.format(args.cmd)) - sys.stdout.flush() + fold_start('exec.command', 'Execute command {}'.format(args.cmd)) sp.check_call(' '.join(args.cmd), shell=True) + fold_end('exec.command', 'Execute command {}'.format(args.cmd)) def with_vcvars(cmd): '''re-exec main script with a (hopefully different) command @@ -702,6 +735,10 @@ call "{vcvars}" {arch} "{python}" "{self}" {cmd} '''.format(**info) + print('{0}Calling vcvars-trampoline.bat to set environment for {1} on {2}{3}' + .format(ANSI_YELLOW, CC, ci_platform, ANSI_RESET)) + sys.stdout.flush() + logger.debug('----- Creating vcvars-trampoline.bat -----') for line in script.split('\n'): logger.debug(line) @@ -710,9 +747,6 @@ call "{vcvars}" {arch} with open('vcvars-trampoline.bat', 'w') as F: F.write(script) - print('{0}Calling vcvars-trampoline.bat to set environment for {1} on {2}{3}' - .format(ANSI_YELLOW, CC, ci_platform, ANSI_RESET)) - sys.stdout.flush() returncode = sp.call('vcvars-trampoline.bat', shell=True) if returncode != 0: sys.exit(returncode) From 5c8d3c20e895986c9bdeb2eae15d71b6f54411d0 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sun, 31 May 2020 11:38:22 +0200 Subject: [PATCH 17/55] cue: refactoring to avoid warnings --- cue.py | 174 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 73 deletions(-) diff --git a/cue.py b/cue.py index 0eea319..39f9cbd 100644 --- a/cue.py +++ b/cue.py @@ -65,7 +65,7 @@ else: ci_configuration += '-optimized' logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', - ci_service, ci_compiler, ci_os, ci_platform, ci_configuration) + ci_service, ci_compiler, ci_os, ci_platform, ci_configuration) curdir = os.getcwd() ci_scriptsdir = os.path.abspath(os.path.dirname(sys.argv[0])) @@ -94,6 +94,7 @@ ANSI_CYAN = "\033[36;1m" ANSI_RESET = "\033[0m" ANSI_CLEAR = "\033[0K" + # Travis log fold control # from https://github.com/travis-ci/travis-rubies/blob/build/build.sh @@ -106,6 +107,7 @@ def fold_start(tag, title): .format(ANSI_YELLOW, title, ANSI_RESET)) sys.stdout.flush() + def fold_end(tag, title): if ci_service == 'travis': print('\ntravis_fold:end:{0}\r' @@ -115,6 +117,7 @@ def fold_end(tag, title): .format(ANSI_YELLOW, title, ANSI_RESET)) sys.stdout.flush() + if 'HomeDrive' in os.environ: cachedir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.cache') toolsdir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.tools') @@ -132,7 +135,7 @@ vcvars_table = { # https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History 'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'], 'vs2017': [r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat', - r'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat'], + r'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat'], 'vs2015': [r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat'], 'vs2013': [r'C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat'], 'vs2012': [r'C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat'], @@ -146,6 +149,7 @@ for key in vcvars_table: if os.path.exists(dir): vcvars_found[key] = dir + def modlist(): if building_base: ret = [] @@ -158,10 +162,12 @@ def modlist(): ret = ['BASE'] + setup['ADD_MODULES'].upper().split() + setup['MODULES'].upper().split() return ret + isbase314 = False has_test_results = False silent_dep_builds = True + def host_info(): print('{0}Build using {1} compiler on {2} ({3}) hosted by {4}{5}' .format(ANSI_CYAN, ci_compiler, ci_os, ci_platform, ci_service, ANSI_RESET)) @@ -174,10 +180,11 @@ def host_info(): print('platform =', distutils.util.get_platform()) print('{0}Available Visual Studio versions{1}'.format(ANSI_CYAN, ANSI_RESET)) - for key in vcvars_found: - print(key, 'in', vcvars_found[key]) + for comp in vcvars_found: + print(comp, 'in', vcvars_found[comp]) sys.stdout.flush() + # Used from unittests def clear_lists(): global isbase314, has_test_results @@ -188,11 +195,13 @@ def clear_lists(): isbase314 = False has_test_results = False + # Error-handler to make shutil.rmtree delete read-only files on Windows def remove_readonly(func, path, excinfo): os.chmod(path, stat.S_IWRITE) func(path) + # source_set(setup) # # Source a settings file (extension .set) found in the setup_dirs path @@ -201,7 +210,7 @@ def source_set(name): # allowed separators: colon or whitespace setup_dirs = os.getenv('SETUP_PATH', "").replace(':', ' ').split() if len(setup_dirs) == 0: - raise NameError("{0}Search path for setup files (SETUP_PATH) is empty{1}".format(ANSI_RED,ANSI_RESET)) + raise NameError("{0}Search path for setup files (SETUP_PATH) is empty{1}".format(ANSI_RED, ANSI_RESET)) for set_dir in setup_dirs: set_file = os.path.join(set_dir, name) + ".set" @@ -234,6 +243,7 @@ def source_set(name): raise NameError("{0}Setup file {1} does not exist in SETUP_PATH search path ({2}){3}" .format(ANSI_RED, name, setup_dirs, ANSI_RESET)) + # update_release_local(var, location) # var name of the variable to set in RELEASE.local # location location (absolute path) of where variable should point to @@ -253,13 +263,13 @@ def update_release_local(var, location): os.makedirs(cachedir) except: pass - fout = open(release_local, 'w') - fout.close() + touch = open(release_local, 'w') + touch.close() base_line = '' found = False logger.debug("Opening RELEASE.local for adding '%s'", updated_line) for line in fileinput.input(release_local, inplace=1): - outputline = line.strip() + output_line = line.strip() if 'EPICS_BASE=' in line: base_line = line.strip() logger.debug("Found EPICS_BASE line '%s', not writing it", base_line) @@ -267,25 +277,27 @@ def update_release_local(var, location): elif '{0}='.format(var) in line: logger.debug("Found '%s=' line, replacing", var) found = True - outputline = updated_line - logger.debug("Writing line to RELEASE.local: '%s'", outputline) - print(outputline) + output_line = updated_line + logger.debug("Writing line to RELEASE.local: '%s'", output_line) + print(output_line) fileinput.close() - fout = open(release_local,"a") + release_local = open(release_local, "a") if not found: logger.debug("Adding new definition: '%s'", updated_line) - print(updated_line, file=fout) + print(updated_line, file=release_local) if base_line: logger.debug("Writing EPICS_BASE line: '%s'", base_line) - print(base_line, file=fout) - fout.close() + print(base_line, file=release_local) + release_local.close() + def set_setup_from_env(dep): for postf in ['', '_DIRNAME', '_REPONAME', '_REPOOWNER', '_REPOURL', '_VARNAME', '_RECURSIVE', '_DEPTH', '_HOOK']: - if dep+postf in os.environ: - setup[dep+postf] = os.environ[dep+postf] - logger.debug('ENV assignment: %s = %s', dep+postf, setup[dep+postf]) + if dep + postf in os.environ: + setup[dep + postf] = os.environ[dep + postf] + logger.debug('ENV assignment: %s = %s', dep + postf, setup[dep + postf]) + def call_git(args, **kws): if 'cwd' in kws: @@ -298,6 +310,7 @@ def call_git(args, **kws): logger.debug('EXEC DONE') return exitcode + def call_make(args=[], **kws): place = kws.get('cwd', os.getcwd()) parallel = kws.pop('parallel', 2) @@ -316,6 +329,7 @@ def call_make(args=[], **kws): if exitcode != 0: sys.exit(exitcode) + def get_git_hash(place): logger.debug("EXEC 'git log -n1 --pretty=format:%%H' in %s", place) sys.stdout.flush() @@ -323,18 +337,20 @@ def get_git_hash(place): logger.debug('EXEC DONE') return head + def complete_setup(dep): set_setup_from_env(dep) setup.setdefault(dep, 'master') - setup.setdefault(dep+"_DIRNAME", dep.lower()) - setup.setdefault(dep+"_REPONAME", dep.lower()) + setup.setdefault(dep + "_DIRNAME", dep.lower()) + setup.setdefault(dep + "_REPONAME", dep.lower()) setup.setdefault('REPOOWNER', 'epics-modules') - setup.setdefault(dep+"_REPOOWNER", setup['REPOOWNER']) - setup.setdefault(dep+"_REPOURL", 'https://github.com/{0}/{1}.git' - .format(setup[dep+'_REPOOWNER'], setup[dep+'_REPONAME'])) - setup.setdefault(dep+"_VARNAME", dep) - setup.setdefault(dep+"_RECURSIVE", 'YES') - setup.setdefault(dep+"_DEPTH", -1) + setup.setdefault(dep + "_REPOOWNER", setup['REPOOWNER']) + setup.setdefault(dep + "_REPOURL", 'https://github.com/{0}/{1}.git' + .format(setup[dep + '_REPOOWNER'], setup[dep + '_REPONAME'])) + setup.setdefault(dep + "_VARNAME", dep) + setup.setdefault(dep + "_RECURSIVE", 'YES') + setup.setdefault(dep + "_DEPTH", -1) + # add_dependency(dep, tag) # @@ -351,7 +367,7 @@ def complete_setup(dep): # - Add $dep_VARNAME line to the RELEASE.local file in the cache area (unless already there) # - Add full path to $modules_to_compile def add_dependency(dep): - recurse = setup[dep+'_RECURSIVE'].lower() + recurse = setup[dep + '_RECURSIVE'].lower() if recurse not in ['0', 'no']: recursearg = ["--recursive"] elif recurse not in ['1', 'yes']: @@ -359,20 +375,20 @@ def add_dependency(dep): else: raise RuntimeError("Invalid value for {}_RECURSIVE='{}' not 0/NO/1/YES".format(dep, recurse)) deptharg = { - '-1':['--depth', '5'], - '0':[], - }.get(str(setup[dep+'_DEPTH']), ['--depth', str(setup[dep+'_DEPTH'])]) + '-1': ['--depth', '5'], + '0': [], + }.get(str(setup[dep + '_DEPTH']), ['--depth', str(setup[dep + '_DEPTH'])]) tag = setup[dep] logger.debug('Adding dependency %s with tag %s', dep, setup[dep]) # determine if dep points to a valid release or branch - if call_git(['ls-remote', '--quiet', '--exit-code', '--refs', setup[dep+'_REPOURL'], tag]): + if call_git(['ls-remote', '--quiet', '--exit-code', '--refs', setup[dep + '_REPOURL'], tag]): raise RuntimeError("{0}{1} is neither a tag nor a branch name for {2} ({3}){4}" - .format(ANSI_RED, tag, dep, setup[dep+'_REPOURL'], ANSI_RESET)) + .format(ANSI_RED, tag, dep, setup[dep + '_REPOURL'], ANSI_RESET)) - dirname = setup[dep+'_DIRNAME']+'-{0}'.format(tag) + dirname = setup[dep + '_DIRNAME'] + '-{0}'.format(tag) place = os.path.join(cachedir, dirname) checked_file = os.path.join(place, "checked_out") @@ -401,7 +417,8 @@ def add_dependency(dep): print('Cloning {0} of dependency {1} into {2}' .format(tag, dep, place)) sys.stdout.flush() - call_git(['clone', '--quiet'] + deptharg + recursearg + ['--branch', tag, setup[dep+'_REPOURL'], dirname], cwd=cachedir) + call_git(['clone', '--quiet'] + deptharg + recursearg + ['--branch', tag, setup[dep + '_REPOURL'], dirname], + cwd=cachedir) sp.check_call(['git', 'log', '-n1'], cwd=place) modules_to_compile.append(place) @@ -424,10 +441,10 @@ def add_dependency(dep): print('-include $(TOP)/../RELEASE.local', file=fout) # run hook if defined - if dep+'_HOOK' in setup: - hook = os.path.join(place, setup[dep+'_HOOK']) + if dep + '_HOOK' in setup: + hook = os.path.join(place, setup[dep + '_HOOK']) if os.path.exists(hook): - print('Running hook {0} in {1}'.format(setup[dep+'_HOOK'], place)) + print('Running hook {0} in {1}'.format(setup[dep + '_HOOK'], place)) sys.stdout.flush() sp.check_call(hook, shell=True, cwd=place) @@ -438,7 +455,8 @@ def add_dependency(dep): print(head, file=fout) fout.close() - update_release_local(setup[dep+"_VARNAME"], place) + update_release_local(setup[dep + "_VARNAME"], place) + def setup_for_build(args): global make, isbase314, has_test_results @@ -470,13 +488,15 @@ def setup_for_build(args): if 'INCLUDE' not in os.environ: os.environ['INCLUDE'] = '' if ci_platform == 'x86': - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', - os.environ['INCLUDE']]) + os.environ['INCLUDE'] = os.pathsep.join( + [r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', + os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', os.environ['PATH']]) elif ci_platform == 'x64': - os.environ['INCLUDE'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', - os.environ['INCLUDE']]) + os.environ['INCLUDE'] = os.pathsep.join( + [r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', + os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', os.environ['PATH']]) if ci_service == 'travis': @@ -518,13 +538,13 @@ def setup_for_build(args): lines = f.readlines() for line in lines: (mod, place) = line.strip().split('=') - bindir = os.path.join(place, 'bin', os.environ['EPICS_HOST_ARCH']) - if os.path.isdir(bindir): - dllpaths.append(bindir) + bin_dir = os.path.join(place, 'bin', os.environ['EPICS_HOST_ARCH']) + if os.path.isdir(bin_dir): + dllpaths.append(bin_dir) # Add DLL location to PATH - bindir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) - if os.path.isdir(bindir): - dllpaths.append(bindir) + bin_dir = os.path.join(os.getcwd(), 'bin', os.environ['EPICS_HOST_ARCH']) + if os.path.isdir(bin_dir): + dllpaths.append(bin_dir) os.environ['PATH'] = os.pathsep.join(dllpaths + [os.environ['PATH']]) logger.debug('DLL paths added to PATH: %s', os.pathsep.join(dllpaths)) @@ -551,11 +571,12 @@ def setup_for_build(args): addpaths.append(path.format(**os.environ)) except KeyError: print('Environment') - [print(' ',K,'=',repr(V)) for K,V in os.environ.items()] + [print(' ', K, '=', repr(V)) for K, V in os.environ.items()] raise os.environ['PATH'] = os.pathsep.join([os.environ['PATH']] + addpaths) + def prepare(args): host_info() @@ -574,7 +595,7 @@ def prepare(args): kvs.sort() [logger.debug(' %s = "%s"', *kv) for kv in kvs] - logger.debug('Effective module list: %s', ret) + logger.debug('Effective module list: %s', modlist()) # we're working with tags (detached heads) a lot: suppress advice call_git(['config', '--global', 'advice.detachedHead', 'false']) @@ -668,7 +689,7 @@ endif''' if not building_base: fold_start('build.dependencies', 'Build missing/outdated dependencies') for mod in modlist(): - place = places[setup[mod+"_VARNAME"]] + place = places[setup[mod + "_VARNAME"]] print('{0}Building dependency {1} in {2}{3}'.format(ANSI_YELLOW, mod, place, ANSI_RESET)) call_make(cwd=place, silent=silent_dep_builds) fold_end('build.dependencies', 'Build missing/outdated dependencies') @@ -677,19 +698,21 @@ endif''' print('Module Tag Binaries Commit') print(100 * '-') for mod in modlist(): - commit = sp.check_output(['git', 'log', '-n1', '--oneline'], cwd=places[setup[mod+"_VARNAME"]]).strip() + commit = sp.check_output(['git', 'log', '-n1', '--oneline'], cwd=places[setup[mod + "_VARNAME"]]).strip() print("%-10s %-12s %-11s %s" % (mod, setup[mod], 'rebuilt', commit)) print('{0}Contents of RELEASE.local{1}'.format(ANSI_CYAN, ANSI_RESET)) with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: print(f.read().strip()) + def build(args): setup_for_build(args) fold_start('build.module', 'Build the main module') call_make(args.makeargs) fold_end('build.module', 'Build the main module') + def test(args): setup_for_build(args) fold_start('test.module', 'Run the main module tests') @@ -701,6 +724,7 @@ def test(args): call_make(['runtests']) fold_end('test.module', 'Run the main module tests') + def doExec(args): 'exec user command with vcvars' setup_for_build(args) @@ -709,6 +733,7 @@ def doExec(args): sp.check_call(' '.join(args.cmd), shell=True) fold_end('exec.command', 'Execute command {}'.format(args.cmd)) + def with_vcvars(cmd): '''re-exec main script with a (hopefully different) command ''' @@ -719,17 +744,17 @@ def with_vcvars(cmd): info = { 'python': sys.executable, 'self': sys.argv[0], - 'cmd':cmd, + 'cmd': cmd, } info['arch'] = { - 'x86': 'x86', # 'amd64_x86' ?? + 'x86': 'x86', # 'amd64_x86' ?? 'x64': 'amd64', - }[ci_platform] # 'x86' or 'x64' + }[ci_platform] # 'x86' or 'x64' info['vcvars'] = vcvars_found[CC] - script=''' + script = ''' call "{vcvars}" {arch} "{python}" "{self}" {cmd} @@ -751,30 +776,32 @@ call "{vcvars}" {arch} if returncode != 0: sys.exit(returncode) + def getargs(): from argparse import ArgumentParser, REMAINDER - P = ArgumentParser() - P.add_argument('--no-vcvars', dest='vcvars', default=True, action='store_false', + p = ArgumentParser() + p.add_argument('--no-vcvars', dest='vcvars', default=True, action='store_false', help='Assume vcvarsall.bat has already been run') - P.add_argument('--add-path', dest='paths', default=[], action='append', + p.add_argument('--add-path', dest='paths', default=[], action='append', help='Append directory to %PATH%. Expands {ENVVAR}') - SP = P.add_subparsers() + subp = p.add_subparsers() - CMD = SP.add_parser('prepare') - CMD.set_defaults(func=prepare) + cmd = subp.add_parser('prepare') + cmd.set_defaults(func=prepare) - CMD = SP.add_parser('build') - CMD.add_argument('makeargs', nargs=REMAINDER) - CMD.set_defaults(func=build) + cmd = subp.add_parser('build') + cmd.add_argument('makeargs', nargs=REMAINDER) + cmd.set_defaults(func=build) - CMD = SP.add_parser('test') - CMD.set_defaults(func=test) + cmd = subp.add_parser('test') + cmd.set_defaults(func=test) - CMD = SP.add_parser('exec') - CMD.add_argument('cmd', nargs=REMAINDER) - CMD.set_defaults(func=doExec) + cmd = subp.add_parser('exec') + cmd.add_argument('cmd', nargs=REMAINDER) + cmd.set_defaults(func=doExec) + + return p - return P def main(raw): global silent_dep_builds @@ -785,10 +812,11 @@ def main(raw): if args.vcvars and ci_compiler.startswith('vs'): # re-exec with MSVC in PATH - with_vcvars(' '.join(['--no-vcvars']+raw)) + with_vcvars(' '.join(['--no-vcvars'] + raw)) else: args.func(args) -if __name__=='__main__': + +if __name__ == '__main__': main(sys.argv[1:]) From 4f01e9039bc178bee73145cb94422dfe447c61aa Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 1 Jun 2020 15:46:14 +0200 Subject: [PATCH 18/55] cue: set EPICS_BASE = '.' for base builds --- cue.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cue.py b/cue.py index 39f9cbd..8fd90e7 100644 --- a/cue.py +++ b/cue.py @@ -459,7 +459,7 @@ def add_dependency(dep): def setup_for_build(args): - global make, isbase314, has_test_results + global isbase314, has_test_results dllpaths = [] if ci_os == 'windows': @@ -517,6 +517,8 @@ def setup_for_build(args): (mod, place) = line.strip().split('=') if mod == 'EPICS_BASE': places['EPICS_BASE'] = place + else: + places['EPICS_BASE'] = '.' if 'EPICS_HOST_ARCH' not in os.environ: logger.debug('Detecting EPICS host architecture in %s', places['EPICS_BASE']) From d3b36cac7400367eeb1352efc0eda366b6c6a618 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 1 Jun 2020 15:58:10 +0200 Subject: [PATCH 19/55] cue: run check for Visual Studio versions only on Windows --- cue.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cue.py b/cue.py index 8fd90e7..cfcbda9 100644 --- a/cue.py +++ b/cue.py @@ -179,9 +179,11 @@ def host_info(): print(' ', dname) print('platform =', distutils.util.get_platform()) - print('{0}Available Visual Studio versions{1}'.format(ANSI_CYAN, ANSI_RESET)) - for comp in vcvars_found: - print(comp, 'in', vcvars_found[comp]) + if ci_os == 'windows': + print('{0}Available Visual Studio versions{1}'.format(ANSI_CYAN, ANSI_RESET)) + for comp in vcvars_found: + print(comp, 'in', vcvars_found[comp]) + sys.stdout.flush() From 772fc3a09af9fd6a62147e2ff4825d9e3db007ee Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 1 Jun 2020 14:35:29 +0200 Subject: [PATCH 20/55] cue-test: refactoring for v3.0 structure and names --- appveyor-test.py => cue-test.py | 209 +++++++++++++++++--------------- 1 file changed, 109 insertions(+), 100 deletions(-) rename appveyor-test.py => cue-test.py (75%) diff --git a/appveyor-test.py b/cue-test.py similarity index 75% rename from appveyor-test.py rename to cue-test.py index 8cfbf94..b70f67f 100644 --- a/appveyor-test.py +++ b/cue-test.py @@ -1,8 +1,8 @@ #!/usr/bin/env python -"""Module ci-scripts AppVeyor unit tests +"""Module ci-scripts unit tests """ -# SET=test00 in the environment (.appveyor.yml) runs the tests in this script +# SET=test00 in the environment and run the tests in this script # all other jobs are started as compile jobs from __future__ import print_function @@ -17,26 +17,30 @@ from argparse import Namespace builddir = os.getcwd() + def find_in_file(regex, filename): - file = open (filename, "r") + file = open(filename, "r") for line in file: if re.search(regex, line): return True return False + def getStringIO(): - if (sys.version_info > (3, 0)): + if sys.version_info > (3, 0): import io return io.StringIO() else: import StringIO return StringIO.StringIO() -sys.path.append('appveyor') -import do + +sys.path.append('.') +import cue # we're working with tags (detached heads) a lot: suppress advice -do.call_git(['config', '--global', 'advice.detachedHead', 'false']) +cue.call_git(['config', '--global', 'advice.detachedHead', 'false']) + class TestSourceSet(unittest.TestCase): @@ -44,56 +48,56 @@ class TestSourceSet(unittest.TestCase): os.environ['SETUP_PATH'] = '.:appveyor' if 'BASE' in os.environ: del os.environ['BASE'] - do.clear_lists() + cue.clear_lists() os.chdir(builddir) def test_EmptySetupDirsPath(self): del os.environ['SETUP_PATH'] - self.assertRaisesRegexp(NameError, '\(SETUP_PATH\) is empty', do.source_set, 'test01') + self.assertRaisesRegexp(NameError, '\(SETUP_PATH\) is empty', cue.source_set, 'test01') def test_InvalidSetupName(self): - self.assertRaisesRegexp(NameError, 'does not exist in SETUP_PATH', do.source_set, 'xxdoesnotexistxx') + self.assertRaisesRegexp(NameError, 'does not exist in SETUP_PATH', cue.source_set, 'xxdoesnotexistxx') def test_ValidSetupName(self): capturedOutput = getStringIO() sys.stdout = capturedOutput - do.source_set('test01') + cue.source_set('test01') sys.stdout = sys.__stdout__ - self.assertEqual(do.setup['BASE'], '7.0', 'BASE was not set to \'7.0\'') + self.assertEqual(cue.setup['BASE'], '7.0', 'BASE was not set to \'7.0\'') def test_SetupDoesNotOverridePreset(self): os.environ['BASE'] = 'foo' capturedOutput = getStringIO() sys.stdout = capturedOutput - do.source_set('test01') + cue.source_set('test01') sys.stdout = sys.__stdout__ - self.assertEqual(do.setup['BASE'], 'foo', + self.assertEqual(cue.setup['BASE'], 'foo', 'Preset BASE was overridden by test01 setup (expected \'foo\' got {0})' - .format(do.setup['BASE'])) + .format(cue.setup['BASE'])) def test_IncludeSetupFirstSetWins(self): - capturedOutput = getStringIO() - sys.stdout = capturedOutput - do.source_set('test02') + captured_output = getStringIO() + sys.stdout = captured_output + cue.source_set('test02') sys.stdout = sys.__stdout__ - self.assertEqual(do.setup['BASE'], 'foo', + self.assertEqual(cue.setup['BASE'], 'foo', 'BASE set in test02 was overridden by test01 setup (expected \'foo\' got {0})' - .format(do.setup['BASE'])) - self.assertEqual(do.setup['FOO'], 'bar', 'Setting of single word does not work') - self.assertEqual(do.setup['FOO2'], 'bar bar2', 'Setting of multiple words does not work') - self.assertEqual(do.setup['FOO3'], 'bar bar2', 'Indented setting of multiple words does not work') - self.assertEqual(do.setup['SNCSEQ'], 'R2-2-7', 'Setup test01 was not included') + .format(cue.setup['BASE'])) + self.assertEqual(cue.setup['FOO'], 'bar', 'Setting of single word does not work') + self.assertEqual(cue.setup['FOO2'], 'bar bar2', 'Setting of multiple words does not work') + self.assertEqual(cue.setup['FOO3'], 'bar bar2', 'Indented setting of multiple words does not work') + self.assertEqual(cue.setup['SNCSEQ'], 'R2-2-7', 'Setup test01 was not included') def test_DoubleIncludeGetsIgnored(self): capturedOutput = getStringIO() sys.stdout = capturedOutput - do.source_set('test03') + cue.source_set('test03') sys.stdout = sys.__stdout__ self.assertRegexpMatches(capturedOutput.getvalue(), 'Ignoring already included setup file') -class TestUpdateReleaseLocal(unittest.TestCase): - release_local = os.path.join(do.cachedir, 'RELEASE.local') +class TestUpdateReleaseLocal(unittest.TestCase): + release_local = os.path.join(cue.cachedir, 'RELEASE.local') def setUp(self): if os.path.exists(self.release_local): @@ -101,7 +105,7 @@ class TestUpdateReleaseLocal(unittest.TestCase): os.chdir(builddir) def test_SetModule(self): - do.update_release_local('MOD1', '/foo/bar') + cue.update_release_local('MOD1', '/foo/bar') found = 0 for line in fileinput.input(self.release_local, inplace=1): if 'MOD1=' in line: @@ -111,10 +115,10 @@ class TestUpdateReleaseLocal(unittest.TestCase): self.assertEqual(found, 1, 'MOD1 not written once to RELEASE.local (found {0})'.format(found)) def test_SetBaseAndMultipleModules(self): - do.update_release_local('EPICS_BASE', '/bar/foo') - do.update_release_local('MOD1', '/foo/bar') - do.update_release_local('MOD2', '/foo/bar2') - do.update_release_local('MOD1', '/foo/bar1') + cue.update_release_local('EPICS_BASE', '/bar/foo') + cue.update_release_local('MOD1', '/foo/bar') + cue.update_release_local('MOD2', '/foo/bar2') + cue.update_release_local('MOD1', '/foo/bar1') found = {} foundat = {} for line in fileinput.input(self.release_local, inplace=1): @@ -158,10 +162,10 @@ class TestUpdateReleaseLocal(unittest.TestCase): self.assertGreater(foundat['mod2'], foundat['mod1'], 'MOD2 (line {0}) appears before MOD1 (line {1})'.format(foundat['mod2'], foundat['mod1'])) -class TestAddDependencyUpToDateCheck(unittest.TestCase): +class TestAddDependencyUpToDateCheck(unittest.TestCase): hash_3_15_6 = "ce7943fb44beb22b453ddcc0bda5398fadf72096" - location = os.path.join(do.cachedir, 'base-R3.15.6') + location = os.path.join(cue.cachedir, 'base-R3.15.6') licensefile = os.path.join(location, 'LICENSE') checked_file = os.path.join(location, 'checked_out') release_file = os.path.join(location, 'configure', 'RELEASE') @@ -169,15 +173,15 @@ class TestAddDependencyUpToDateCheck(unittest.TestCase): def setUp(self): os.environ['SETUP_PATH'] = '.:appveyor' if os.path.exists(self.location): - shutil.rmtree(self.location, onerror=do.remove_readonly) - do.clear_lists() + shutil.rmtree(self.location, onerror=cue.remove_readonly) + cue.clear_lists() os.chdir(builddir) - do.source_set('defaults') - do.complete_setup('BASE') + cue.source_set('defaults') + cue.complete_setup('BASE') def test_MissingDependency(self): - do.setup['BASE'] = 'R3.15.6' - do.add_dependency('BASE') + cue.setup['BASE'] = 'R3.15.6' + cue.add_dependency('BASE') self.assertTrue(os.path.exists(self.licensefile), 'Missing dependency was not checked out') self.assertTrue(os.path.exists(self.checked_file), 'Checked-out commit marker was not written') with open(self.checked_file, 'r') as bfile: @@ -190,20 +194,20 @@ class TestAddDependencyUpToDateCheck(unittest.TestCase): 'RELEASE in Base includes TOP/../RELEASE.local') def test_UpToDateDependency(self): - do.setup['BASE'] = 'R3.15.6' - do.add_dependency('BASE') + cue.setup['BASE'] = 'R3.15.6' + cue.add_dependency('BASE') os.remove(self.licensefile) - do.add_dependency('BASE') + cue.add_dependency('BASE') self.assertFalse(os.path.exists(self.licensefile), 'Check out on top of existing up-to-date dependency') def test_OutdatedDependency(self): - do.setup['BASE'] = 'R3.15.6' - do.add_dependency('BASE') + cue.setup['BASE'] = 'R3.15.6' + cue.add_dependency('BASE') os.remove(self.licensefile) with open(self.checked_file, "w") as fout: print('XXX not the right hash XXX', file=fout) fout.close() - do.add_dependency('BASE') + cue.add_dependency('BASE') self.assertTrue(os.path.exists(self.licensefile), 'No check-out on top of out-of-date dependency') with open(self.checked_file, 'r') as bfile: checked_out = bfile.read().strip() @@ -212,6 +216,7 @@ class TestAddDependencyUpToDateCheck(unittest.TestCase): "Wrong commit of dependency checked out (expected='{0}' found='{1}')" .format(self.hash_3_15_6, checked_out)) + def is_shallow_repo(place): check = sp.check_output(['git', 'rev-parse', '--is-shallow-repository'], cwd=place).strip() if check == '--is-shallow-repository': @@ -221,64 +226,65 @@ def is_shallow_repo(place): check = 'false' return check == 'true' -class TestAddDependencyOptions(unittest.TestCase): - location = os.path.join(do.cachedir, 'mcoreutils-master') +class TestAddDependencyOptions(unittest.TestCase): + location = os.path.join(cue.cachedir, 'mcoreutils-master') testfile = os.path.join(location, '.ci', 'LICENSE') def setUp(self): os.environ['SETUP_PATH'] = '.:appveyor' - if os.path.exists(do.cachedir): - shutil.rmtree(do.cachedir, onerror=do.remove_readonly) - do.clear_lists() - do.source_set('defaults') - do.complete_setup('MCoreUtils') - do.setup['MCoreUtils'] = 'master' + if os.path.exists(cue.cachedir): + shutil.rmtree(cue.cachedir, onerror=cue.remove_readonly) + cue.clear_lists() + cue.source_set('defaults') + cue.complete_setup('MCoreUtils') + cue.setup['MCoreUtils'] = 'master' def test_Default(self): - do.add_dependency('MCoreUtils') + cue.add_dependency('MCoreUtils') self.assertTrue(os.path.exists(self.testfile), 'Submodule (.ci) not checked out recursively (requested: default=YES') self.assertTrue(is_shallow_repo(self.location), 'Module not checked out shallow (requested: default=5)') def test_SetRecursiveNo(self): - do.setup['MCoreUtils_RECURSIVE'] = 'NO' - do.add_dependency('MCoreUtils') + cue.setup['MCoreUtils_RECURSIVE'] = 'NO' + cue.add_dependency('MCoreUtils') self.assertFalse(os.path.exists(self.testfile), 'Submodule (.ci) checked out recursively') def test_SetDepthZero(self): - do.setup['MCoreUtils_DEPTH'] = '0' - do.add_dependency('MCoreUtils') + cue.setup['MCoreUtils_DEPTH'] = '0' + cue.add_dependency('MCoreUtils') self.assertFalse(is_shallow_repo(self.location), 'Module checked out shallow (requested full)') def test_SetDepthThree(self): - do.setup['MCoreUtils_DEPTH'] = '3' - do.add_dependency('MCoreUtils') + cue.setup['MCoreUtils_DEPTH'] = '3' + cue.add_dependency('MCoreUtils') self.assertTrue(is_shallow_repo(self.location), 'Module not checked out shallow (requested: default=5)') def test_AddMsiTo314(self): - do.complete_setup('BASE') - do.setup['BASE'] = 'R3.14.12.1' - msifile = os.path.join(do.cachedir, 'base-R3.14.12.1', 'src', 'dbtools', 'msi.c') - do.add_dependency('BASE') + cue.complete_setup('BASE') + cue.setup['BASE'] = 'R3.14.12.1' + msifile = os.path.join(cue.cachedir, 'base-R3.14.12.1', 'src', 'dbtools', 'msi.c') + cue.add_dependency('BASE') self.assertTrue(os.path.exists(msifile), 'MSI was not added to Base 3.14') + def repo_access(dep): - do.set_setup_from_env(dep) - do.setup.setdefault(dep + "_DIRNAME", dep.lower()) - do.setup.setdefault(dep + "_REPONAME", dep.lower()) - do.setup.setdefault('REPOOWNER', 'epics-modules') - do.setup.setdefault(dep + "_REPOOWNER", do.setup['REPOOWNER']) - do.setup.setdefault(dep + "_REPOURL", 'https://github.com/{0}/{1}.git' - .format(do.setup[dep + '_REPOOWNER'], do.setup[dep + '_REPONAME'])) + cue.set_setup_from_env(dep) + cue.setup.setdefault(dep + "_DIRNAME", dep.lower()) + cue.setup.setdefault(dep + "_REPONAME", dep.lower()) + cue.setup.setdefault('REPOOWNER', 'epics-modules') + cue.setup.setdefault(dep + "_REPOOWNER", cue.setup['REPOOWNER']) + cue.setup.setdefault(dep + "_REPOURL", 'https://github.com/{0}/{1}.git' + .format(cue.setup[dep + '_REPOOWNER'], cue.setup[dep + '_REPONAME'])) with open(os.devnull, 'w') as devnull: - return do.call_git(['ls-remote', '--quiet', '--heads', do.setup[dep + '_REPOURL']], - stdout=devnull, stderr=devnull) + return cue.call_git(['ls-remote', '--quiet', '--heads', cue.setup[dep + '_REPOURL']], + stdout=devnull, stderr=devnull) + class TestDefaultModuleURLs(unittest.TestCase): - modules = ['BASE', 'PVDATA', 'PVACCESS', 'NTYPES', 'SNCSEQ', 'STREAM', 'ASYN', 'STD', 'CALC', 'AUTOSAVE', 'BUSY', 'SSCAN', @@ -286,14 +292,15 @@ class TestDefaultModuleURLs(unittest.TestCase): def setUp(self): os.environ['SETUP_PATH'] = '.:appveyor' - do.clear_lists() + cue.clear_lists() os.chdir(builddir) - do.source_set('defaults') + cue.source_set('defaults') def test_Repos(self): for mod in self.modules: self.assertEqual(repo_access(mod), 0, 'Defaults for {0} do not point to a valid git repository at {1}' - .format(mod, do.setup[mod + '_REPOURL'])) + .format(mod, cue.setup[mod + '_REPOURL'])) + class TestVCVars(unittest.TestCase): def test_vcvars(self): @@ -301,18 +308,19 @@ class TestVCVars(unittest.TestCase): or distutils.util.get_platform() != "win32": raise unittest.SkipTest() - do.with_vcvars('env') + cue.with_vcvars('env') + class TestSetupForBuild(unittest.TestCase): configuration = os.environ['CONFIGURATION'] platform = os.environ['PLATFORM'] cc = os.environ['CMP'] args = Namespace(paths=[]) - do.building_base = True + cue.building_base = True def setUp(self): os.environ.pop('EPICS_HOST_ARCH', None) - do.clear_lists() + cue.clear_lists() def tearDown(self): os.environ['CONFIGURATION'] = self.configuration @@ -322,7 +330,7 @@ class TestSetupForBuild(unittest.TestCase): def test_AddPathsOption(self): os.environ['FOOBAR'] = 'BAR' args = Namespace(paths=['/my/{FOOBAR}/dir', '/my/foobar']) - do.setup_for_build(args) + cue.setup_for_build(args) self.assertTrue(re.search('/my/BAR/dir', os.environ['PATH']), 'Expanded path not in PATH') self.assertTrue(re.search('/foobar', os.environ['PATH']), 'Plain path not in PATH') os.environ.pop('FOOBAR', None) @@ -330,7 +338,7 @@ class TestSetupForBuild(unittest.TestCase): def test_HostArchConfiguration(self): for config in ['dynamic', 'dynamic-debug', 'static', 'static-debug']: os.environ['CONFIGURATION'] = config - do.setup_for_build(self.args) + cue.setup_for_build(self.args) self.assertTrue('EPICS_HOST_ARCH' in os.environ, 'EPICS_HOST_ARCH is not set for Configuration={0}'.format(config)) if re.search('static', config): @@ -355,7 +363,7 @@ class TestSetupForBuild(unittest.TestCase): os.environ['PLATFORM'] = platform os.environ['CMP'] = cc os.environ['CONFIGURATION'] = 'dynamic' - do.setup_for_build(self.args) + cue.setup_for_build(self.args) self.assertTrue('EPICS_HOST_ARCH' in os.environ, 'EPICS_HOST_ARCH is not set for {0} / {1}'.format(cc, platform)) if platform == 'x86': @@ -376,9 +384,9 @@ class TestSetupForBuild(unittest.TestCase): self.assertTrue(re.search(pattern, os.environ['INCLUDE']), 'Include location for {0} not in INCLUDE'.format(pattern)) - def test_StrawberryInPath(self): + def test_StrawberryInPathVS2019(self): os.environ['CMP'] = 'vs2019' - do.setup_for_build(self.args) + cue.setup_for_build(self.args) self.assertTrue(re.search('strawberry', os.environ['PATH'], flags=re.IGNORECASE), 'Strawberry Perl location not in PATH for vs2019') @@ -398,40 +406,41 @@ class TestSetupForBuild(unittest.TestCase): def test_DetectionBase314No(self): self.setBase314('NO') - do.setup_for_build(self.args) - self.assertFalse(do.isbase314, 'Falsely detected Base 3.14') + cue.setup_for_build(self.args) + self.assertFalse(cue.isbase314, 'Falsely detected Base 3.14') def test_DetectionBase314Yes(self): self.setBase314('YES') - do.setup_for_build(self.args) - self.assertTrue(do.isbase314, 'Base 3.14 = YES not detected') + cue.setup_for_build(self.args) + self.assertTrue(cue.isbase314, 'Base 3.14 = YES not detected') def test_DetectionTestResultsTarget314No(self): self.setBase314('YES') self.setTestResultsTarget('nottherighttarget') - do.setup_for_build(self.args) - self.assertFalse(do.has_test_results, 'Falsely detected test-results target') + cue.setup_for_build(self.args) + self.assertFalse(cue.has_test_results, 'Falsely detected test-results target') def test_DetectionTestResultsTarget314Yes(self): self.setBase314('YES') self.setTestResultsTarget('test-results') - do.setup_for_build(self.args) - self.assertFalse(do.has_test_results, 'Falsely found test-results on Base 3.14') + cue.setup_for_build(self.args) + self.assertFalse(cue.has_test_results, 'Falsely found test-results on Base 3.14') def test_DetectionTestResultsTargetNot314Yes(self): self.setBase314('NO') self.setTestResultsTarget('test-results') - do.setup_for_build(self.args) - self.assertTrue(do.has_test_results, 'Target test-results not detected') + cue.setup_for_build(self.args) + self.assertTrue(cue.has_test_results, 'Target test-results not detected') + if __name__ == "__main__": if 'VV' in os.environ and os.environ['VV'] == '1': logging.basicConfig(level=logging.DEBUG) - do.silent_dep_builds = False + cue.silent_dep_builds = False - do.host_info() - if sys.argv[1:]==['env']: + cue.host_info() + if sys.argv[1:] == ['env']: # testing with_vcvars - [print(K,'=',V) for K, V in os.environ.items()] + [print(K, '=', V) for K, V in os.environ.items()] else: unittest.main() From f456e47904c9c1d491ca7be38343b944959d22c1 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 2 Jun 2020 20:22:29 +0200 Subject: [PATCH 21/55] travis: fix unit tests and run/skip them fixes #10 --- .travis.yml | 18 +++++++++ cue-test.py | 108 ++++++++++++++++++++++++++++------------------------ 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7776b92..46e71f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,6 +63,24 @@ script: jobs: include: +# Run unit tests + + - env: SET=test00 + install: python cue-test.py env + script: python cue-test.py + + - env: SET=test00 + os: osx + install: python cue-test.py env + script: python cue-test.py + + - env: SET=test00 + os: windows + install: python cue-test.py env + script: python cue-test.py + +# Compile example + - env: SET=test01 - env: SET=test01 BCFG=static diff --git a/cue-test.py b/cue-test.py index b70f67f..6250bb8 100644 --- a/cue-test.py +++ b/cue-test.py @@ -86,7 +86,7 @@ class TestSourceSet(unittest.TestCase): self.assertEqual(cue.setup['FOO'], 'bar', 'Setting of single word does not work') self.assertEqual(cue.setup['FOO2'], 'bar bar2', 'Setting of multiple words does not work') self.assertEqual(cue.setup['FOO3'], 'bar bar2', 'Indented setting of multiple words does not work') - self.assertEqual(cue.setup['SNCSEQ'], 'R2-2-7', 'Setup test01 was not included') + self.assertEqual(cue.setup['SNCSEQ'], 'R2-2-8', 'Setup test01 was not included') def test_DoubleIncludeGetsIgnored(self): capturedOutput = getStringIO() @@ -312,9 +312,6 @@ class TestVCVars(unittest.TestCase): class TestSetupForBuild(unittest.TestCase): - configuration = os.environ['CONFIGURATION'] - platform = os.environ['PLATFORM'] - cc = os.environ['CMP'] args = Namespace(paths=[]) cue.building_base = True @@ -323,9 +320,8 @@ class TestSetupForBuild(unittest.TestCase): cue.clear_lists() def tearDown(self): - os.environ['CONFIGURATION'] = self.configuration - os.environ['PLATFORM'] = self.platform - os.environ['CMP'] = self.cc + os.environ.pop('EPICS_HOST_ARCH', None) + cue.clear_lists() def test_AddPathsOption(self): os.environ['FOOBAR'] = 'BAR' @@ -335,60 +331,74 @@ class TestSetupForBuild(unittest.TestCase): self.assertTrue(re.search('/foobar', os.environ['PATH']), 'Plain path not in PATH') os.environ.pop('FOOBAR', None) + @unittest.skipIf(cue.ci_os != 'windows', 'HostArchConfiguration test only applies to windows') def test_HostArchConfiguration(self): - for config in ['dynamic', 'dynamic-debug', 'static', 'static-debug']: - os.environ['CONFIGURATION'] = config - cue.setup_for_build(self.args) - self.assertTrue('EPICS_HOST_ARCH' in os.environ, - 'EPICS_HOST_ARCH is not set for Configuration={0}'.format(config)) - if re.search('static', config): - self.assertTrue(re.search('-static$', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is not -static for Configuration={0}'.format(config)) - self.assertFalse(re.search('debug', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is -debug for Configuration={0}'.format(config)) - elif re.search('debug', config): - self.assertFalse(re.search('static', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is -static for Configuration={0}'.format(config)) - self.assertTrue(re.search('-debug$', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is not -debug for Configuration={0}'.format(config)) - else: - self.assertFalse(re.search('static', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is -static for Configuration={0}'.format(config)) - self.assertFalse(re.search('debug', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is -debug for Configuration={0}'.format(config)) - - def test_HostArchPlatform(self): - for platform in ['x86', 'x64', 'X64']: - for cc in ['vs2019', 'mingw']: - os.environ['PLATFORM'] = platform - os.environ['CMP'] = cc - os.environ['CONFIGURATION'] = 'dynamic' + cue.ci['compiler'] = 'vs2017' + for cue.ci['debug'] in [True, False]: + for cue.ci['static'] in [True, False]: + config_st = {True: 'static', False: 'shared'} + config_db = {True: '-debug', False: '-optimized'} + config = config_st[cue.ci['static']] + config_db[cue.ci['debug']] cue.setup_for_build(self.args) self.assertTrue('EPICS_HOST_ARCH' in os.environ, - 'EPICS_HOST_ARCH is not set for {0} / {1}'.format(cc, platform)) + 'EPICS_HOST_ARCH is not set for Configuration={0}'.format(config)) + if cue.ci['static']: + self.assertTrue(re.search('-static$', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH is not -static for Configuration={0}'.format(config)) + self.assertFalse(re.search('debug', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH is -debug for Configuration={0}'.format(config)) + elif cue.ci['debug']: + self.assertFalse(re.search('static', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH (found {0}) is -static for Configuration={1}' + .format(os.environ['EPICS_HOST_ARCH'], config)) + self.assertTrue(re.search('-debug$', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH (found {0}) is not -debug for Configuration={1}' + .format(os.environ['EPICS_HOST_ARCH'], config)) + else: + self.assertFalse(re.search('static', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH is -static for Configuration={0}'.format(config)) + self.assertFalse(re.search('debug', os.environ['EPICS_HOST_ARCH']), + 'EPICS_HOST_ARCH is -debug for Configuration={0}'.format(config)) + + @unittest.skipIf(cue.ci_os != 'windows', 'HostArchPlatform test only applies to windows') + def test_HostArchPlatform(self): + if ci_service == 'travis': + platforms = ['x64'] + else: + platforms = ['x86', 'x64'] + for platform in platforms: + for cc in ['vs2019', 'gcc']: + cue.ci['platform'] = platform + cue.ci['compiler'] = cc + cue.setup_for_build(self.args) + self.assertTrue('EPICS_HOST_ARCH' in os.environ, + 'EPICS_HOST_ARCH is not set for {0} / {1}' + .format(cc, cue.ci['platform'])) if platform == 'x86': self.assertTrue(re.search('^win32-x86', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is not win32-x86 for {0} / {1}'.format(cc, platform)) + 'EPICS_HOST_ARCH (found {0}) is not win32-x86 for {1} / {2}' + .format(os.environ['EPICS_HOST_ARCH'], cc, platform)) else: self.assertTrue(re.search('^windows-x64', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is not windows-x64 for {0} / {1}'.format(cc, platform)) - if cc == 'mingw': + 'EPICS_HOST_ARCH (found {0}) is not windows-x64 for {1} / {2}' + .format(os.environ['EPICS_HOST_ARCH'], cc, platform)) + if cc == 'gcc': self.assertTrue(re.search('-mingw$', os.environ['EPICS_HOST_ARCH']), - 'EPICS_HOST_ARCH is not -mingw for {0} / {1}'.format(cc, platform)) - if platform == 'x86': - pattern = 'mingw32' - else: - pattern = 'mingw64' - self.assertTrue(re.search(pattern, os.environ['PATH']), - 'Binary location for {0} not in PATH'.format(pattern)) - self.assertTrue(re.search(pattern, os.environ['INCLUDE']), - 'Include location for {0} not in INCLUDE'.format(pattern)) + 'EPICS_HOST_ARCH (found {0}) is not -mingw for {1} / {2}' + .format(os.environ['EPICS_HOST_ARCH'], cc, platform)) + pattern = {'x86': 'mingw32', 'x64': 'mingw64'} + self.assertTrue(re.search(pattern[platform], os.environ['PATH']), + 'Binary location for {0} not in PATH (found {1})' + .format(pattern[platform], os.environ['PATH'])) + @unittest.skipIf(cue.ci_os != 'windows', 'Strawberry perl test only applies to windows') def test_StrawberryInPathVS2019(self): - os.environ['CMP'] = 'vs2019' + if 'APPVEYOR' in os.environ: + os.environ['CMP'] = 'vs2019' cue.setup_for_build(self.args) self.assertTrue(re.search('strawberry', os.environ['PATH'], flags=re.IGNORECASE), - 'Strawberry Perl location not in PATH for vs2019') + 'Strawberry Perl installed but location not in PATH (found {0})' + .format(os.environ['PATH'])) def setBase314(self, yesno): cfg_base_version = os.path.join('configure', 'CONFIG_BASE_VERSION') From 9ea849eed364dc1a4f2fd92af3bb268bb839730f Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 2 Jun 2020 19:36:27 +0200 Subject: [PATCH 22/55] cue: make detect_context() a function and ci a dict for better testability --- cue-test.py | 25 +++++-- cue.py | 200 +++++++++++++++++++++++++++------------------------- 2 files changed, 125 insertions(+), 100 deletions(-) diff --git a/cue-test.py b/cue-test.py index 6250bb8..e6ba858 100644 --- a/cue-test.py +++ b/cue-test.py @@ -17,6 +17,20 @@ from argparse import Namespace builddir = os.getcwd() +# Detect basic context (service, os) +if 'TRAVIS' in os.environ: + ci_service = 'travis' + ci_os = os.environ['TRAVIS_OS_NAME'] + +if 'APPVEYOR' in os.environ: + ci_service = 'appveyor' + if re.match(r'^Visual', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'windows' + elif re.match(r'^Ubuntu', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'linux' + elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci_os = 'osx' + def find_in_file(regex, filename): file = open(filename, "r") @@ -232,10 +246,11 @@ class TestAddDependencyOptions(unittest.TestCase): testfile = os.path.join(location, '.ci', 'LICENSE') def setUp(self): - os.environ['SETUP_PATH'] = '.:appveyor' + os.environ['SETUP_PATH'] = '.' if os.path.exists(cue.cachedir): shutil.rmtree(cue.cachedir, onerror=cue.remove_readonly) cue.clear_lists() + cue.detect_context() cue.source_set('defaults') cue.complete_setup('MCoreUtils') cue.setup['MCoreUtils'] = 'master' @@ -318,6 +333,7 @@ class TestSetupForBuild(unittest.TestCase): def setUp(self): os.environ.pop('EPICS_HOST_ARCH', None) cue.clear_lists() + cue.detect_context() def tearDown(self): os.environ.pop('EPICS_HOST_ARCH', None) @@ -331,7 +347,7 @@ class TestSetupForBuild(unittest.TestCase): self.assertTrue(re.search('/foobar', os.environ['PATH']), 'Plain path not in PATH') os.environ.pop('FOOBAR', None) - @unittest.skipIf(cue.ci_os != 'windows', 'HostArchConfiguration test only applies to windows') + @unittest.skipIf(ci_os != 'windows', 'HostArchConfiguration test only applies to windows') def test_HostArchConfiguration(self): cue.ci['compiler'] = 'vs2017' for cue.ci['debug'] in [True, False]: @@ -360,7 +376,7 @@ class TestSetupForBuild(unittest.TestCase): self.assertFalse(re.search('debug', os.environ['EPICS_HOST_ARCH']), 'EPICS_HOST_ARCH is -debug for Configuration={0}'.format(config)) - @unittest.skipIf(cue.ci_os != 'windows', 'HostArchPlatform test only applies to windows') + @unittest.skipIf(ci_os != 'windows', 'HostArchPlatform test only applies to windows') def test_HostArchPlatform(self): if ci_service == 'travis': platforms = ['x64'] @@ -391,7 +407,7 @@ class TestSetupForBuild(unittest.TestCase): 'Binary location for {0} not in PATH (found {1})' .format(pattern[platform], os.environ['PATH'])) - @unittest.skipIf(cue.ci_os != 'windows', 'Strawberry perl test only applies to windows') + @unittest.skipIf(ci_os != 'windows', 'Strawberry perl test only applies to windows') def test_StrawberryInPathVS2019(self): if 'APPVEYOR' in os.environ: os.environ['CMP'] = 'vs2019' @@ -448,6 +464,7 @@ if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) cue.silent_dep_builds = False + cue.detect_context() cue.host_info() if sys.argv[1:] == ['env']: # testing with_vcvars diff --git a/cue.py b/cue.py index cfcbda9..302189c 100644 --- a/cue.py +++ b/cue.py @@ -13,77 +13,95 @@ import distutils.util logger = logging.getLogger(__name__) -# Detect the service and set up environment accordingly -ci_service = '' -ci_os = '' -ci_platform = '' -ci_compiler = '' -ci_static = False -ci_debug = False -ci_choco = ['make'] +# Detect the service and set up context hash accordingly +def detect_context(): + if 'TRAVIS' in os.environ: + ci['service'] = 'travis' + ci['os'] = os.environ['TRAVIS_OS_NAME'] + ci['platform'] = 'x64' + ci['compiler'] = os.environ['TRAVIS_COMPILER'] + if ci['os'] == 'windows': + ci['choco'].append('strawberryperl') + if re.match(r'^vs', ci['compiler']): + # Only Visual Studio 2017 available + ci['compiler'] = 'vs2017' + if 'BCFG' in os.environ: + if re.search('static', os.environ['BCFG']): + ci['static'] = True + if re.search('debug', os.environ['BCFG']): + ci['debug'] = True -if 'TRAVIS' in os.environ: - ci_service = 'travis' - ci_os = os.environ['TRAVIS_OS_NAME'] - ci_platform = 'x64' - ci_compiler = os.environ['TRAVIS_COMPILER'] - if ci_os == 'windows': - ci_choco.append('strawberryperl') - if re.match(r'^vs', ci_compiler): - # Only Visual Studio 2017 available - ci_compiler = 'vs2017' - if 'BCFG' in os.environ: - if re.search('static', os.environ['BCFG']): - ci_static = True - if re.search('debug', os.environ['BCFG']): - ci_debug = True + if 'APPVEYOR' in os.environ: + ci['service'] = 'appveyor' + if re.match(r'^Visual', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci['os'] = 'windows' + elif re.match(r'^Ubuntu', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci['os'] = 'linux' + elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): + ci['os'] = 'osx' + ci['platform'] = os.environ['PLATFORM'].lower() + if 'CMP' in os.environ: + ci['compiler'] = os.environ['CMP'] + if re.search('static', os.environ['CONFIGURATION']): + ci['static'] = True + if re.search('debug', os.environ['CONFIGURATION']): + ci['debug'] = True -if 'APPVEYOR' in os.environ: - ci_service = 'appveyor' - if re.match(r'^Visual', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): - ci_os = 'windows' - elif re.match(r'^Ubuntu', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): - ci_os = 'linux' - elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']): - ci_os = 'osx' - ci_platform = os.environ['PLATFORM'].lower() - if 'CMP' in os.environ: - ci_compiler = os.environ['CMP'] - if re.search('static', os.environ['CONFIGURATION']): - ci_static = True - if re.search('debug', os.environ['CONFIGURATION']): - ci_debug = True + if ci['static']: + ci['configuration'] = 'static' + else: + ci['configuration'] = 'shared' + if ci['debug']: + ci['configuration'] += '-debug' + else: + ci['configuration'] += '-optimized' -if ci_static: - ci_configuration = 'static' -else: - ci_configuration = 'shared' -if ci_debug: - ci_configuration += '-debug' -else: - ci_configuration += '-optimized' + ci['scriptsdir'] = os.path.abspath(os.path.dirname(sys.argv[0])) + + if 'CHOCO' in os.environ: + ci['choco'].extend(os.environ['CHOCO'].split()) + + logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', + ci['service'], ci['compiler'], ci['os'], ci['platform'], ci['configuration']) -logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', - ci_service, ci_compiler, ci_os, ci_platform, ci_configuration) curdir = os.getcwd() -ci_scriptsdir = os.path.abspath(os.path.dirname(sys.argv[0])) +ci = {} seen_setups = [] modules_to_compile = [] setup = {} places = {} + +def clear_lists(): + global isbase314, has_test_results, ci + del seen_setups[:] + del modules_to_compile[:] + setup.clear() + places.clear() + isbase314 = False + has_test_results = False + ci['service'] = '' + ci['os'] = '' + ci['platform'] = '' + ci['compiler'] = '' + ci['static'] = False + ci['debug'] = False + ci['configuration'] = '' + ci['scriptsdir'] = '' + ci['choco'] = ['make'] + + +clear_lists() + if 'BASE' in os.environ and os.environ['BASE'] == 'SELF': building_base = True places['EPICS_BASE'] = curdir else: building_base = False -if 'CHOCO' in os.environ: - ci_choco.extend(os.environ['CHOCO'].split()) - # Setup ANSI Colors ANSI_RED = "\033[31;1m" ANSI_GREEN = "\033[32;1m" @@ -99,7 +117,7 @@ ANSI_CLEAR = "\033[0K" # from https://github.com/travis-ci/travis-rubies/blob/build/build.sh def fold_start(tag, title): - if ci_service == 'travis': + if ci['service'] == 'travis': print('travis_fold:start:{0}{1}{2}{3}' .format(tag, ANSI_YELLOW, title, ANSI_RESET)) elif ci['service'] == 'appveyor': @@ -109,10 +127,10 @@ def fold_start(tag, title): def fold_end(tag, title): - if ci_service == 'travis': + if ci['service'] == 'travis': print('\ntravis_fold:end:{0}\r' .format(tag), end='') - elif ci_service == 'appveyor': + elif ci['service'] == 'appveyor': print('{0}----- /\\ /\\ /\\ ----- END: {1} -----{2}' .format(ANSI_YELLOW, title, ANSI_RESET)) sys.stdout.flush() @@ -170,7 +188,7 @@ silent_dep_builds = True def host_info(): print('{0}Build using {1} compiler on {2} ({3}) hosted by {4}{5}' - .format(ANSI_CYAN, ci_compiler, ci_os, ci_platform, ci_service, ANSI_RESET)) + .format(ANSI_CYAN, ci['compiler'], ci['os'], ci['platform'], ci['service'], ANSI_RESET)) print('{0}Python setup{1}'.format(ANSI_CYAN, ANSI_RESET)) print(sys.version) @@ -179,7 +197,7 @@ def host_info(): print(' ', dname) print('platform =', distutils.util.get_platform()) - if ci_os == 'windows': + if ci['os'] == 'windows': print('{0}Available Visual Studio versions{1}'.format(ANSI_CYAN, ANSI_RESET)) for comp in vcvars_found: print(comp, 'in', vcvars_found[comp]) @@ -187,17 +205,6 @@ def host_info(): sys.stdout.flush() -# Used from unittests -def clear_lists(): - global isbase314, has_test_results - del seen_setups[:] - del modules_to_compile[:] - setup.clear() - places.clear() - isbase314 = False - has_test_results = False - - # Error-handler to make shutil.rmtree delete read-only files on Windows def remove_readonly(func, path, excinfo): os.chmod(path, stat.S_IWRITE) @@ -433,7 +440,7 @@ def add_dependency(dep): if 'BASE_3_14=YES' in f.read(): print('Adding MSI 1.7 to {0}'.format(place)) sys.stdout.flush() - sp.check_call(['patch', '-p1', '-i', os.path.join(ci_scriptsdir, 'add-msi-to-314.patch')], + sp.check_call(['patch', '-p1', '-i', os.path.join(ci['scriptsdir'], 'add-msi-to-314.patch')], cwd=place) else: # force including RELEASE.local for non-base modules by overwriting their configure/RELEASE @@ -464,51 +471,51 @@ def setup_for_build(args): global isbase314, has_test_results dllpaths = [] - if ci_os == 'windows': - if re.match(r'^vs', ci_compiler): + if ci['os'] == 'windows': + if re.match(r'^vs', ci['compiler']): # there is no combined static and debug EPICS_HOST_ARCH target, # so a combined debug and static target will appear to be just static # but debug will have been specified in CONFIG_SITE by prepare() hostarchsuffix = '' - if ci_debug: + if ci['debug']: hostarchsuffix = '-debug' - if ci_static: + if ci['static']: hostarchsuffix = '-static' - if ci_platform == 'x86': + if ci['platform'] == 'x86': os.environ['EPICS_HOST_ARCH'] = 'win32-x86' + hostarchsuffix - elif ci_platform == 'x64': + elif ci['platform'] == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix - if ci_service == 'appveyor': - if ci_compiler == 'vs2019': + if ci['service'] == 'appveyor': + if ci['compiler'] == 'vs2019': # put strawberry perl in the PATH os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'), os.path.join(r'C:\Strawberry\perl\bin'), os.environ['PATH']]) - if ci_compiler == 'gcc': + if ci['compiler'] == 'gcc': if 'INCLUDE' not in os.environ: os.environ['INCLUDE'] = '' - if ci_platform == 'x86': + if ci['platform'] == 'x86': os.environ['INCLUDE'] = os.pathsep.join( [r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include', os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin', os.environ['PATH']]) - elif ci_platform == 'x64': + elif ci['platform'] == 'x64': os.environ['INCLUDE'] = os.pathsep.join( [r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include', os.environ['INCLUDE']]) os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin', os.environ['PATH']]) - if ci_service == 'travis': + if ci['service'] == 'travis': os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\perl\site\bin', r'C:\Strawberry\perl\bin', os.environ['PATH']]) - if ci_compiler == 'gcc': - if ci_platform == 'x86': + if ci['compiler'] == 'gcc': + if ci['platform'] == 'x86': os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' - elif ci_platform == 'x64': + elif ci['platform'] == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' # Find BASE location @@ -536,7 +543,7 @@ def setup_for_build(args): eha, os.environ['EPICS_HOST_ARCH']) break - if ci_os == 'windows': + if ci['os'] == 'windows': if not building_base: with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: lines = f.readlines() @@ -620,19 +627,19 @@ def prepare(args): fold_start('set.up.epics_build', 'Configuring EPICS build system') with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as config_site: - if ci_static: + if ci['static']: config_site.write('SHARED_LIBRARIES=NO\n') config_site.write('STATIC_BUILD=YES\n') linktype = 'static' else: linktype = 'dynamic (DLL)' - if ci_debug: + if ci['debug']: config_site.write('HOST_OPT=NO\n') optitype = 'debug' else: optitype = 'optimized' - if ci_os == 'windows' and re.match(r'^vs', ci_compiler): + if ci['os'] == 'windows' and re.match(r'^vs', ci['compiler']): # Enable/fix parallel build for VisualStudio compiler on older Base versions add_vs_fix = True config_win = os.path.join(places['EPICS_BASE'], 'configure', 'os', 'CONFIG.win32-x86.win32-x86') @@ -666,9 +673,9 @@ endif''' if not os.path.isdir(toolsdir): os.makedirs(toolsdir) - if ci_os == 'windows' and ci_choco: + if ci['os'] == 'windows' and ci['choco']: fold_start('install.choco', 'Installing CHOCO packages') - sp.check_call(['choco', 'install'] + ci_choco) + sp.check_call(['choco', 'install'] + ci['choco']) fold_end('install.choco', 'Installing CHOCO packages') setup_for_build(args) @@ -681,7 +688,7 @@ endif''' sys.stdout.flush() sp.check_call(['perl', '--version']) - if ci_compiler == 'gcc': + if ci['compiler'] == 'gcc': print('{0}$ gcc --version{1}'.format(ANSI_CYAN, ANSI_RESET)) sys.stdout.flush() sp.check_call(['gcc', '--version']) @@ -741,7 +748,7 @@ def doExec(args): def with_vcvars(cmd): '''re-exec main script with a (hopefully different) command ''' - CC = ci_compiler + CC = ci['compiler'] # cf. https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line @@ -754,7 +761,7 @@ def with_vcvars(cmd): info['arch'] = { 'x86': 'x86', # 'amd64_x86' ?? 'x64': 'amd64', - }[ci_platform] # 'x86' or 'x64' + }[ci['platform']] # 'x86' or 'x64' info['vcvars'] = vcvars_found[CC] @@ -765,7 +772,7 @@ call "{vcvars}" {arch} '''.format(**info) print('{0}Calling vcvars-trampoline.bat to set environment for {1} on {2}{3}' - .format(ANSI_YELLOW, CC, ci_platform, ANSI_RESET)) + .format(ANSI_YELLOW, CC, ci['platform'], ANSI_RESET)) sys.stdout.flush() logger.debug('----- Creating vcvars-trampoline.bat -----') @@ -814,10 +821,11 @@ def main(raw): logging.basicConfig(level=logging.DEBUG) silent_dep_builds = False - if args.vcvars and ci_compiler.startswith('vs'): + detect_context() + + if args.vcvars and ci['compiler'].startswith('vs'): # re-exec with MSVC in PATH with_vcvars(' '.join(['--no-vcvars'] + raw)) - else: args.func(args) From cdfea8ec7068f295fa288d9249044932e48544d1 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Tue, 2 Jun 2020 16:16:22 +0200 Subject: [PATCH 23/55] cue-test: add DetectContext tests for Travis --- cue-test.py | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/cue-test.py b/cue-test.py index e6ba858..61d0509 100644 --- a/cue-test.py +++ b/cue-test.py @@ -326,6 +326,180 @@ class TestVCVars(unittest.TestCase): cue.with_vcvars('env') +class TestDetectContext(unittest.TestCase): + def tearDown(self): + cue.clear_lists() + os.environ.pop('BCFG', None) + + def test_TravisLinuxGccNone(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'linux', "ci['os'] is {0} (expected: linux)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'gcc', "ci['compiler'] is {0} (expected: gcc)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + + def test_TravisLinuxClangNone(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'clang' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'linux', "ci['os'] is {0} (expected: linux)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'clang', "ci['compiler'] is {0} (expected: clang)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + + def test_TravisBcfgShared(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + os.environ['BCFG'] = 'shared' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + + def test_TravisBcfgStatic(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + os.environ['BCFG'] = 'static' + cue.detect_context() + self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'static-optimized', + "ci['configuration'] is {0} (expected: static-optimized)" + .format(cue.ci['configuration'])) + + def test_TravisBcfgDebug(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + os.environ['BCFG'] = 'debug' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertTrue(cue.ci['debug'], "ci['debug'] is False (expected: True)") + self.assertEqual(cue.ci['configuration'], 'shared-debug', + "ci['configuration'] is {0} (expected: shared-debug)" + .format(cue.ci['configuration'])) + + def test_TravisBcfgStaticDebug(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + os.environ['BCFG'] = 'static-debug' + cue.detect_context() + self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") + self.assertTrue(cue.ci['debug'], "ci['debug'] is False (expected: True)") + self.assertEqual(cue.ci['configuration'], 'static-debug', + "ci['configuration'] is {0} (expected: static-debug)" + .format(cue.ci['configuration'])) + + def test_TravisWindowsGccNone(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'windows' + os.environ['TRAVIS_COMPILER'] = 'gcc' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'gcc', "ci['compiler'] is {0} (expected: gcc)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + def test_TravisWindowsVs2017None(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'windows' + os.environ['TRAVIS_COMPILER'] = 'vs2017' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'vs2017', "ci['compiler'] is {0} (expected: vs2017)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + def test_TravisWindowsVs2019None(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'windows' + os.environ['TRAVIS_COMPILER'] = 'vs2019' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'vs2017', "ci['compiler'] is {0} (expected: vs2017)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + def test_TravisOsxClangNone(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'osx' + os.environ['TRAVIS_COMPILER'] = 'clang' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'osx', "ci['os'] is {0} (expected: osx)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'clang', "ci['compiler'] is {0} (expected: clang)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + + class TestSetupForBuild(unittest.TestCase): args = Namespace(paths=[]) cue.building_base = True From a0f1c7e96e52d92cb45923a87c4292801c22709a Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 3 Jun 2020 11:16:41 +0200 Subject: [PATCH 24/55] travis: add Linux builds - bionic, trusty, clang fixes #30 --- .travis.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.travis.yml b/.travis.yml index 46e71f1..8a4f5fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,6 +81,18 @@ jobs: # Compile example + - env: SET=test01 + dist: bionic + + - env: SET=test01 BCFG=static-debug + dist: bionic + + - env: SET=test01 + dist: trusty + + - env: SET=test01 BCFG=static-debug + dist: trusty + - env: SET=test01 - env: SET=test01 BCFG=static @@ -89,6 +101,12 @@ jobs: - env: SET=test01 BCFG=static-debug + - env: SET=test01 + compiler: clang + + - env: SET=test01 BCFG=static-debug + compiler: clang + - env: SET=test01 os: windows From 58cebdd7ddd038bcb0a78a58c87dbd06b3fda4f8 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 3 Jun 2020 15:48:20 +0200 Subject: [PATCH 25/55] Check make version for "-O" support fixes #33 --- cue-test.py | 6 ++++-- cue.py | 32 ++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/cue-test.py b/cue-test.py index 61d0509..3a4ecfe 100644 --- a/cue-test.py +++ b/cue-test.py @@ -503,6 +503,8 @@ class TestDetectContext(unittest.TestCase): class TestSetupForBuild(unittest.TestCase): args = Namespace(paths=[]) cue.building_base = True + if ci_os == 'windows': + sp.check_call(['choco', 'install', 'make']) def setUp(self): os.environ.pop('EPICS_HOST_ARCH', None) @@ -607,12 +609,12 @@ class TestSetupForBuild(unittest.TestCase): def test_DetectionBase314No(self): self.setBase314('NO') cue.setup_for_build(self.args) - self.assertFalse(cue.isbase314, 'Falsely detected Base 3.14') + self.assertFalse(cue.is_base314, 'Falsely detected Base 3.14') def test_DetectionBase314Yes(self): self.setBase314('YES') cue.setup_for_build(self.args) - self.assertTrue(cue.isbase314, 'Base 3.14 = YES not detected') + self.assertTrue(cue.is_base314, 'Base 3.14 = YES not detected') def test_DetectionTestResultsTarget314No(self): self.setBase314('YES') diff --git a/cue.py b/cue.py index 302189c..acc6b3d 100644 --- a/cue.py +++ b/cue.py @@ -74,15 +74,22 @@ modules_to_compile = [] setup = {} places = {} +is_base314 = False +is_make3 = False +has_test_results = False +silent_dep_builds = True + def clear_lists(): - global isbase314, has_test_results, ci + global is_base314, has_test_results, silent_dep_builds, is_make3 del seen_setups[:] del modules_to_compile[:] setup.clear() places.clear() - isbase314 = False + is_base314 = False + is_make3 = False has_test_results = False + silent_dep_builds = True ci['service'] = '' ci['os'] = '' ci['platform'] = '' @@ -181,11 +188,6 @@ def modlist(): return ret -isbase314 = False -has_test_results = False -silent_dep_builds = True - - def host_info(): print('{0}Build using {1} compiler on {2} ({3}) hosted by {4}{5}' .format(ANSI_CYAN, ci['compiler'], ci['os'], ci['platform'], ci['service'], ANSI_RESET)) @@ -325,10 +327,12 @@ def call_make(args=[], **kws): parallel = kws.pop('parallel', 2) silent = kws.pop('silent', False) # no parallel make for Base 3.14 - if parallel <= 0 or isbase314: + if parallel <= 0 or is_base314: makeargs = [] else: - makeargs = ['-j{0}'.format(parallel), '-Otarget'] + makeargs = ['-j{0}'.format(parallel)] + if not is_make3: + makeargs += ['-Otarget'] if silent: makeargs += ['-s'] logger.debug("EXEC '%s' in %s", ' '.join(['make'] + makeargs + args), place) @@ -468,7 +472,7 @@ def add_dependency(dep): def setup_for_build(args): - global isbase314, has_test_results + global is_base314, has_test_results, is_make3 dllpaths = [] if ci['os'] == 'windows': @@ -563,9 +567,9 @@ def setup_for_build(args): if os.path.exists(cfg_base_version): with open(cfg_base_version) as myfile: if 'BASE_3_14=YES' in myfile.read(): - isbase314 = True + is_base314 = True - if not isbase314: + if not is_base314: rules_build = os.path.join(places['EPICS_BASE'], 'configure', 'RULES_BUILD') if os.path.exists(rules_build): with open(rules_build) as myfile: @@ -573,6 +577,10 @@ def setup_for_build(args): if re.match('^test-results:', line): has_test_results = True + # Check make version + if re.match(r'^GNU Make 3', sp.check_output(['make', '-v'])): + is_make3 = True + # apparently %CD% is handled automagically os.environ['TOP'] = os.getcwd() From f57b063f68d0b13e3e58a373e9c8fa5ccb87670e Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 4 Jun 2020 20:37:12 +0200 Subject: [PATCH 26/55] cue: compiler setup for clang, gcc, wine32 and wine64 fixes #30 --- cue.py | 178 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 58 deletions(-) diff --git a/cue.py b/cue.py index acc6b3d..a4ef650 100644 --- a/cue.py +++ b/cue.py @@ -434,7 +434,7 @@ def add_dependency(dep): cwd=cachedir) sp.check_call(['git', 'log', '-n1'], cwd=place) - modules_to_compile.append(place) + modules_to_compile.append(dep) if dep == 'BASE': # add MSI 1.7 to Base 3.14 @@ -471,10 +471,7 @@ def add_dependency(dep): update_release_local(setup[dep + "_VARNAME"], place) -def setup_for_build(args): - global is_base314, has_test_results, is_make3 - dllpaths = [] - +def detect_epics_host_arch(): if ci['os'] == 'windows': if re.match(r'^vs', ci['compiler']): # there is no combined static and debug EPICS_HOST_ARCH target, @@ -491,6 +488,32 @@ def setup_for_build(args): elif ci['platform'] == 'x64': os.environ['EPICS_HOST_ARCH'] = 'windows-x64' + hostarchsuffix + elif ci['compiler'] == 'gcc': + if ci['platform'] == 'x86': + os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' + elif ci['platform'] == 'x64': + os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' + + if 'EPICS_HOST_ARCH' not in os.environ: + logger.debug('Running script to detect EPICS host architecture in %s', places['EPICS_BASE']) + os.environ['EPICS_HOST_ARCH'] = 'unknown' + eha_scripts = [ + os.path.join(places['EPICS_BASE'], 'src', 'tools', 'EpicsHostArch.pl'), + os.path.join(places['EPICS_BASE'], 'startup', 'EpicsHostArch.pl'), + ] + for eha in eha_scripts: + if os.path.exists(eha): + os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]).strip() + logger.debug('%s returned: %s', + eha, os.environ['EPICS_HOST_ARCH']) + break + + +def setup_for_build(args): + global is_base314, has_test_results, is_make3 + dllpaths = [] + + if ci['os'] == 'windows': if ci['service'] == 'appveyor': if ci['compiler'] == 'vs2019': # put strawberry perl in the PATH @@ -516,12 +539,6 @@ def setup_for_build(args): os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\perl\site\bin', r'C:\Strawberry\perl\bin', os.environ['PATH']]) - if ci['compiler'] == 'gcc': - if ci['platform'] == 'x86': - os.environ['EPICS_HOST_ARCH'] = 'win32-x86-mingw' - elif ci['platform'] == 'x64': - os.environ['EPICS_HOST_ARCH'] = 'windows-x64-mingw' - # Find BASE location if not building_base: with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: @@ -533,19 +550,7 @@ def setup_for_build(args): else: places['EPICS_BASE'] = '.' - if 'EPICS_HOST_ARCH' not in os.environ: - logger.debug('Detecting EPICS host architecture in %s', places['EPICS_BASE']) - os.environ['EPICS_HOST_ARCH'] = 'unknown' - eha_scripts = [ - os.path.join(places['EPICS_BASE'], 'src', 'tools', 'EpicsHostArch.pl'), - os.path.join(places['EPICS_BASE'], 'startup', 'EpicsHostArch.pl'), - ] - for eha in eha_scripts: - if os.path.exists(eha): - os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]).strip() - logger.debug('%s returned: %s', - eha, os.environ['EPICS_HOST_ARCH']) - break + detect_epics_host_arch() if ci['os'] == 'windows': if not building_base: @@ -632,33 +637,40 @@ def prepare(args): fold_end('check.out.dependencies', 'Checking/cloning dependencies') - fold_start('set.up.epics_build', 'Configuring EPICS build system') + if 'BASE' in modules_to_compile or building_base: + fold_start('set.up.epics_build', 'Configuring EPICS build system') - with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as config_site: - if ci['static']: - config_site.write('SHARED_LIBRARIES=NO\n') - config_site.write('STATIC_BUILD=YES\n') - linktype = 'static' - else: - linktype = 'dynamic (DLL)' - if ci['debug']: - config_site.write('HOST_OPT=NO\n') - optitype = 'debug' - else: - optitype = 'optimized' + detect_epics_host_arch() + + # Set static/debug in CONFIG_SITE + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + if ci['static']: + f.write('SHARED_LIBRARIES=NO\n') + f.write('STATIC_BUILD=YES\n') + linktype = 'static' + else: + linktype = 'shared (DLL)' + if ci['debug']: + f.write('HOST_OPT=NO\n') + optitype = 'debug' + else: + optitype = 'optimized' + + print('EPICS Base build system set up for {0} build with {1} linking' + .format(optitype, linktype)) - if ci['os'] == 'windows' and re.match(r'^vs', ci['compiler']): # Enable/fix parallel build for VisualStudio compiler on older Base versions - add_vs_fix = True - config_win = os.path.join(places['EPICS_BASE'], 'configure', 'os', 'CONFIG.win32-x86.win32-x86') - with open(config_win) as myfile: - for line in myfile: - if re.match(r'^ifneq \(\$\(VisualStudioVersion\),11\.0\)', line): - add_vs_fix = False - if add_vs_fix: - logger.debug('Adding parallel build fix for VisualStudio to %s', config_win) - with open(config_win, 'a') as myfile: - myfile.write(''' + if ci['os'] == 'windows' and re.match(r'^vs', ci['compiler']): + add_vs_fix = True + config_win = os.path.join(places['EPICS_BASE'], 'configure', 'os', 'CONFIG.win32-x86.win32-x86') + with open(config_win) as f: + for line in f: + if re.match(r'^ifneq \(\$\(VisualStudioVersion\),11\.0\)', line): + add_vs_fix = False + if add_vs_fix: + logger.debug('Adding parallel build fix for VisualStudio to %s', config_win) + with open(config_win, 'a') as f: + f.write(''' # Fix parallel build for some VisualStudio versions ifneq ($(VisualStudioVersion),) ifneq ($(VisualStudioVersion),11.0) @@ -670,13 +682,62 @@ else OPT_CXXFLAGS_NO := $(filter-out -FS,$(OPT_CXXFLAGS_NO)) OPT_CFLAGS_NO := $(filter-out -FS,$(OPT_CFLAGS_NO)) endif -endif''' - ) +endif''') - print('EPICS Base build system set up for {0} build with {1} linking' - .format(optitype, linktype)) + # Cross compilation on Linux to Windows/Wine + # requires wine and g++-mingw-w64-i686 / g++-mingw-w64-x86-64 + if ci['os'] == 'linux' and 'WINE' in os.environ: - fold_end('set.up.epics_build', 'Configuring EPICS build system') + if os.environ['WINE'] == '32': + print('Cross compiler mingw32 / Wine') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG.linux-x86.win32-x86-mingw'), 'a') as f: + f.write(''' +CMPLR_PREFIX=i686-w64-mingw32-''') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + f.write(''' +CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw''') + + if os.environ['WINE'] == '64': + print('Cross compiler mingw64 / Wine') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG.linux-x86.windows-x64-mingw'), 'a') as f: + f.write(''' +CMPLR_PREFIX=x86_64-w64-mingw32-''') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + f.write(''' +CROSS_COMPILER_TARGET_ARCHS+=windows-x64-mingw''') + + host_ccmplr_name = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\1', ci['compiler']) + host_cmplr_ver_suffix = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\3', ci['compiler']) + host_cmpl_ver = host_cmplr_ver_suffix[1:] + + if host_ccmplr_name == 'clang': + print('Host compiler clang') + host_cppcmplr_name = re.sub(r'clang', r'clang++', host_ccmplr_name) + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG_SITE.Common.'+os.environ['EPICS_HOST_ARCH']), 'a') as f: + f.write(''' +GNU = NO +CMPLR_CLASS = clang +CC = {0}{2} +CCC = {1}{2}'''.format(host_ccmplr_name, host_cppcmplr_name, host_cmplr_ver_suffix)) + + # hack + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG.gnuCommon'), 'a') as f: + f.write(''' +CMPLR_CLASS = clang''') + + if host_ccmplr_name == 'gcc': + print('Host compiler gcc') + host_cppcmplr_name = re.sub(r'gcc', r'g++', host_ccmplr_name) + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG_SITE.Common.' + os.environ['EPICS_HOST_ARCH']), 'a') as f: + f.write(''' +CC = {0}{2} +CCC = {1}{2}'''.format(host_ccmplr_name, host_cppcmplr_name, host_cmplr_ver_suffix)) + + fold_end('set.up.epics_build', 'Configuring EPICS build system') if not os.path.isdir(toolsdir): os.makedirs(toolsdir) @@ -696,14 +757,15 @@ endif''' sys.stdout.flush() sp.check_call(['perl', '--version']) - if ci['compiler'] == 'gcc': - print('{0}$ gcc --version{1}'.format(ANSI_CYAN, ANSI_RESET)) - sys.stdout.flush() - sp.check_call(['gcc', '--version']) - else: + if re.match(r'^vs', ci['compiler']): print('{0}$ cl{1}'.format(ANSI_CYAN, ANSI_RESET)) sys.stdout.flush() sp.check_call(['cl']) + else: + cc = ci['compiler'] + print('{0}$ {1} --version{2}'.format(ANSI_CYAN, cc, ANSI_RESET)) + sys.stdout.flush() + sp.check_call([cc, '--version']) if not building_base: fold_start('build.dependencies', 'Build missing/outdated dependencies') From eaffc82e36ad10b5fa3f8e77c722bd1c3421ccfc Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 3 Jun 2020 17:35:16 +0200 Subject: [PATCH 27/55] travis: add wine32, wine64 and osx builds --- .travis.yml | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8a4f5fe..8e9f024 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,11 +94,8 @@ jobs: dist: trusty - env: SET=test01 - - env: SET=test01 BCFG=static - - env: SET=test01 BCFG=debug - - env: SET=test01 BCFG=static-debug - env: SET=test01 @@ -108,29 +105,41 @@ jobs: compiler: clang - env: SET=test01 - os: windows - - - env: SET=test01 BCFG=static - os: windows + os: osx + compiler: clang - env: SET=test01 BCFG=debug - os: windows + os: osx + compiler: clang + - env: SET=test01 WINE=32 TEST=NO + - env: SET=test01 WINE=32 TEST=NO BCFG=static + - env: SET=test01 WINE=32 TEST=NO BCFG=debug + - env: SET=test01 WINE=32 TEST=NO BCFG=static-debug + + - env: SET=test01 WINE=64 TEST=NO + - env: SET=test01 WINE=64 TEST=NO BCFG=static + - env: SET=test01 WINE=64 TEST=NO BCFG=debug + - env: SET=test01 WINE=64 TEST=NO BCFG=static-debug + + - env: SET=test01 + os: windows + - env: SET=test01 BCFG=static + os: windows + - env: SET=test01 BCFG=debug + os: windows - env: SET=test01 BCFG=static-debug os: windows - env: SET=test01 compiler: vs2017 os: windows - - env: SET=test01 BCFG=static compiler: vs2017 os: windows - - env: SET=test01 BCFG=debug compiler: vs2017 os: windows - - env: SET=test01 BCFG=static-debug compiler: vs2017 os: windows From 64908b18ba83723bfd30c1599854a8ddcbfb2b59 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 4 Jun 2020 19:36:45 +0200 Subject: [PATCH 28/55] cue: add additional USR_* flags to CONFIG_SITE --- cue.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cue.py b/cue.py index a4ef650..1fc312e 100644 --- a/cue.py +++ b/cue.py @@ -737,6 +737,21 @@ CMPLR_CLASS = clang''') CC = {0}{2} CCC = {1}{2}'''.format(host_ccmplr_name, host_cppcmplr_name, host_cmplr_ver_suffix)) + # Add additional flags to CONFIG_SITE + flags_text = '' + if 'USR_CPPFLAGS' in os.environ: + flags_text += ''' +USR_CPPFLAGS += {0}'''.format(os.environ['USR_CPPFLAGS']) + if 'USR_CFLAGS' in os.environ: + flags_text += ''' +USR_CFLAGS += {0}'''.format(os.environ['USR_CFLAGS']) + if 'USR_CXXFLAGS' in os.environ: + flags_text += ''' +USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS']) + if flags_text: + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + f.write(flags_text) + fold_end('set.up.epics_build', 'Configuring EPICS build system') if not os.path.isdir(toolsdir): From dd23c6a91f631cbd79943caea567577a20b83c75 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 4 Jun 2020 22:23:53 +0200 Subject: [PATCH 29/55] travis: set base recursive=NO to speed up the test builds (PVA not needed) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8e9f024..cd0448d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ env: - SETUP_PATH=.:.ci - VV=1 - CHOCO=re2c + - BASE_RECURSIVE=NO addons: apt: From 4ca9efe4cf3b3791f7c08e5b278c21f361be183c Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 5 Jun 2020 17:49:07 +0200 Subject: [PATCH 30/55] cue: add RTEMS cross compilation --- cue.py | 81 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/cue.py b/cue.py index 1fc312e..6c4b5a6 100644 --- a/cue.py +++ b/cue.py @@ -22,7 +22,7 @@ def detect_context(): ci['platform'] = 'x64' ci['compiler'] = os.environ['TRAVIS_COMPILER'] if ci['os'] == 'windows': - ci['choco'].append('strawberryperl') + ci['choco'] += ['strawberryperl'] if re.match(r'^vs', ci['compiler']): # Only Visual Studio 2017 available ci['compiler'] = 'vs2017' @@ -143,19 +143,19 @@ def fold_end(tag, title): sys.stdout.flush() +homedir = curdir if 'HomeDrive' in os.environ: - cachedir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.cache') - toolsdir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath'), '.tools') + homedir = os.path.join(os.getenv('HomeDrive'), os.getenv('HomePath')) elif 'HOME' in os.environ: - cachedir = os.path.join(os.getenv('HOME'), '.cache') - toolsdir = os.path.join(os.getenv('HOME'), '.tools') -else: - cachedir = os.path.join('.', '.cache') - toolsdir = os.path.join('.', '.tools') + homedir = os.getenv('HOME') +cachedir = os.path.join(homedir, '.cache') +toolsdir = os.path.join(homedir, '.tools') +rtemsdir = os.path.join(homedir, '.rtems') if 'CACHEDIR' in os.environ: cachedir = os.environ['CACHEDIR'] + vcvars_table = { # https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History 'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'], @@ -684,29 +684,50 @@ else endif endif''') - # Cross compilation on Linux to Windows/Wine - # requires wine and g++-mingw-w64-i686 / g++-mingw-w64-x86-64 - if ci['os'] == 'linux' and 'WINE' in os.environ: + # Cross-compilations from Linux platform + if ci['os'] == 'linux': - if os.environ['WINE'] == '32': - print('Cross compiler mingw32 / Wine') - with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', - 'CONFIG.linux-x86.win32-x86-mingw'), 'a') as f: - f.write(''' + # Cross compilation to Windows/Wine (set WINE to architecture "32", "64") + # requires wine and g++-mingw-w64-i686 / g++-mingw-w64-x86-64 + if 'WINE' in os.environ: + if os.environ['WINE'] == '32': + print('Cross compiler mingw32 / Wine') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG.linux-x86.win32-x86-mingw'), 'a') as f: + f.write(''' CMPLR_PREFIX=i686-w64-mingw32-''') - with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: - f.write(''' + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + f.write(''' CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw''') - if os.environ['WINE'] == '64': - print('Cross compiler mingw64 / Wine') - with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', - 'CONFIG.linux-x86.windows-x64-mingw'), 'a') as f: - f.write(''' + if os.environ['WINE'] == '64': + print('Cross compiler mingw64 / Wine') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG.linux-x86.windows-x64-mingw'), 'a') as f: + f.write(''' CMPLR_PREFIX=x86_64-w64-mingw32-''') + with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: + f.write(''' +CROSS_COMPILER_TARGET_ARCHS += windows-x64-mingw''') + + # Cross compilation on Linux to RTEMS (set RTEMS to version "4.9", "4.10") + # requires qemu, bison, flex, texinfo, install-info + if 'RTEMS' in os.environ: + print('Cross compiler RTEMS{0} @ pc386',format(os.environ['RTEMS'])) + with open(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG_SITE.Common.RTEMS'), 'a') as f: + f.write(''' +RTEMS_VERSION={0} +RTEMS_BASE={1}'''.format(os.environ['RTEMS'], rtemsdir)) + + # Base 3.15 doesn't have -qemu target architecture + qemu_suffix = '' + if os.path.exists(os.path.join(places['EPICS_BASE'], 'configure', 'os', + 'CONFIG.Common.RTEMS-pc386-qemu')): + qemu_suffix = '-qemu' with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f: f.write(''' -CROSS_COMPILER_TARGET_ARCHS+=windows-x64-mingw''') +CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386{0}'''.format(qemu_suffix)) host_ccmplr_name = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\1', ci['compiler']) host_cmplr_ver_suffix = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\3', ci['compiler']) @@ -762,6 +783,18 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS']) sp.check_call(['choco', 'install'] + ci['choco']) fold_end('install.choco', 'Installing CHOCO packages') + if ci['os'] == 'linux' and 'RTEMS' in os.environ: + tar_name = 'i386-rtems{0}-trusty-20171203-{0}.tar.bz2'.format(os.environ['RTEMS']) + print('Downloading RTEMS {0} cross compiler: {1}' + .format(os.environ['RTEMS'], tar_name)) + sys.stdout.flush() + sp.check_call(['curl', '-fsSL', '--retry', '3', '-o', tar_name, + 'https://github.com/mdavidsaver/rsb/releases/download/20171203-{0}/{1}' + .format(os.environ['RTEMS'], tar_name)], + cwd=toolsdir) + sp.check_call(['tar', '-C', '/', '-xmj', '-f', os.path.join(toolsdir, tar_name)]) + os.remove(os.path.join(toolsdir, tar_name)) + setup_for_build(args) print('{0}EPICS_HOST_ARCH = {1}{2}'.format(ANSI_CYAN, os.environ['EPICS_HOST_ARCH'], ANSI_RESET)) From 424fae7d530a64a813b1c6c96c30e2adc21de94e Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 5 Jun 2020 16:59:22 +0200 Subject: [PATCH 31/55] travis: add RTEMS cross compilation jobs --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index cd0448d..da4655e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -123,6 +123,16 @@ jobs: - env: SET=test01 WINE=64 TEST=NO BCFG=debug - env: SET=test01 WINE=64 TEST=NO BCFG=static-debug + - env: SET=test01 RTEMS=4.9 BASE=3.15 TEST=NO + - env: SET=test01 RTEMS=4.9 BASE=3.15 TEST=NO BCFG=static + - env: SET=test01 RTEMS=4.9 BASE=3.15 TEST=NO BCFG=debug + - env: SET=test01 RTEMS=4.9 BASE=3.15 TEST=NO BCFG=static-debug + + - env: SET=test01 RTEMS=4.10 + - env: SET=test01 RTEMS=4.10 BCFG=static + - env: SET=test01 RTEMS=4.10 BCFG=debug + - env: SET=test01 RTEMS=4.10 BCFG=static-debug + - env: SET=test01 os: windows - env: SET=test01 BCFG=static From 0a4a845ff139a85b4825f273f3bfbcad5b832458 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 5 Jun 2020 16:37:43 +0200 Subject: [PATCH 32/55] cue: only rebuild out-of-date dependencies --- cue.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cue.py b/cue.py index 6c4b5a6..07496c3 100644 --- a/cue.py +++ b/cue.py @@ -817,7 +817,7 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS']) if not building_base: fold_start('build.dependencies', 'Build missing/outdated dependencies') - for mod in modlist(): + for mod in modules_to_compile: place = places[setup[mod + "_VARNAME"]] print('{0}Building dependency {1} in {2}{3}'.format(ANSI_YELLOW, mod, place, ANSI_RESET)) call_make(cwd=place, silent=silent_dep_builds) @@ -827,8 +827,12 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS']) print('Module Tag Binaries Commit') print(100 * '-') for mod in modlist(): + if mod in modules_to_compile: + stat = 'rebuilt' + else: + stat = 'from cache' commit = sp.check_output(['git', 'log', '-n1', '--oneline'], cwd=places[setup[mod + "_VARNAME"]]).strip() - print("%-10s %-12s %-11s %s" % (mod, setup[mod], 'rebuilt', commit)) + print("%-10s %-12s %-11s %s" % (mod, setup[mod], stat, commit)) print('{0}Contents of RELEASE.local{1}'.format(ANSI_CYAN, ANSI_RESET)) with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f: From 158bacd256cc0abf25a1a214e3888dc6d3192ca3 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 5 Jun 2020 16:55:08 +0200 Subject: [PATCH 33/55] cue: add separate action for 'test-results' fixes #31 --- cue.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cue.py b/cue.py index 07496c3..8338802 100644 --- a/cue.py +++ b/cue.py @@ -849,15 +849,23 @@ def build(args): def test(args): setup_for_build(args) fold_start('test.module', 'Run the main module tests') - print('{0}Running the main module tests{1}'.format(ANSI_YELLOW, ANSI_RESET)) if has_test_results: call_make(['tapfiles']) - call_make(['test-results'], parallel=0, silent=True) else: call_make(['runtests']) fold_end('test.module', 'Run the main module tests') +def test_results(args): + setup_for_build(args) + fold_start('test.results', 'Sum up main module test results') + if has_test_results: + call_make(['test-results'], parallel=0, silent=True) + else: + print("{0}Base {1} does not implement 'test-results' target{2}".format(ANSI_YELLOW, setup['BASE'], ANSI_RESET)) + fold_end('test.results', 'Sum up main module test results') + + def doExec(args): 'exec user command with vcvars' setup_for_build(args) @@ -929,6 +937,9 @@ def getargs(): cmd = subp.add_parser('test') cmd.set_defaults(func=test) + cmd = subp.add_parser('test-results') + cmd.set_defaults(func=test_results) + cmd = subp.add_parser('exec') cmd.add_argument('cmd', nargs=REMAINDER) cmd.set_defaults(func=doExec) From 5f9760061217f7c99d8dbbc3e282b463daa80c91 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 5 Jun 2020 17:14:40 +0200 Subject: [PATCH 34/55] defaults: set default base branch to 7.0 - add test for default base branch - fixes #40 --- cue-test.py | 5 +++++ defaults.set | 1 + 2 files changed, 6 insertions(+) diff --git a/cue-test.py b/cue-test.py index 3a4ecfe..e576a8d 100644 --- a/cue-test.py +++ b/cue-test.py @@ -285,6 +285,11 @@ class TestAddDependencyOptions(unittest.TestCase): cue.add_dependency('BASE') self.assertTrue(os.path.exists(msifile), 'MSI was not added to Base 3.14') + def test_DefaultBaseBranch(self): + cue.complete_setup('BASE') + self.assertEqual(cue.setup['BASE'], '7.0', + 'Default Base branch is not 7.0 (found {0})'.format(cue.setup['BASE'])) + def repo_access(dep): cue.set_setup_from_env(dep) diff --git a/defaults.set b/defaults.set index 7cc9a32..9f433c5 100644 --- a/defaults.set +++ b/defaults.set @@ -1,4 +1,5 @@ # EPICS Base +BASE=7.0 BASE_DIRNAME=base BASE_REPONAME=epics-base BASE_REPOOWNER=epics-base From be4674e64181012c0da9aac217f81dbcf2c90710 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 14:23:10 +0200 Subject: [PATCH 35/55] example: RTEMS memory fs only on Base 7.0 and above --- exampleApp/test/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exampleApp/test/Makefile b/exampleApp/test/Makefile index cdfc92a..1eefe57 100644 --- a/exampleApp/test/Makefile +++ b/exampleApp/test/Makefile @@ -38,7 +38,9 @@ testHarness_SRCS += epicsRunExampleTests.c exampleTestHarness_SRCS += $(testHarness_SRCS) exampleTestHarness_SRCS_RTEMS += rtemsTestHarness.c +ifdef BASE_7_0 PROD_SRCS_RTEMS += rtemsTestData.c +endif PROD_vxWorks = exampleTestHarness PROD_RTEMS = exampleTestHarness @@ -54,5 +56,7 @@ endif include $(TOP)/configure/RULES +ifdef BASE_7_0 rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) +endif From 6ce24870e5d57bea89fa86b25d9a451dea48ce6c Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sun, 7 Jun 2020 14:24:18 +0200 Subject: [PATCH 36/55] travis: add test and test-results actions --- .travis.yml | 2 ++ cue.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index da4655e..43133a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,8 @@ install: script: - python cue.py build + - python cue.py test + - python cue.py test-results # If you need to do more during install and build, # add a local directory to your module and do e.g. diff --git a/cue.py b/cue.py index 8338802..7d93301 100644 --- a/cue.py +++ b/cue.py @@ -862,7 +862,8 @@ def test_results(args): if has_test_results: call_make(['test-results'], parallel=0, silent=True) else: - print("{0}Base {1} does not implement 'test-results' target{2}".format(ANSI_YELLOW, setup['BASE'], ANSI_RESET)) + print("{0}Base in {1} does not implement 'test-results' target{2}" + .format(ANSI_YELLOW, places['EPICS_BASE'], ANSI_RESET)) fold_end('test.results', 'Sum up main module test results') From 1f8acec2ac0acde6c1bc973524ff31fb7a23b1c5 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 14:45:27 +0200 Subject: [PATCH 37/55] appveyor: update build configurations and cue calls --- .appveyor.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index f7e8f46..967752d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -55,11 +55,11 @@ install: # Default build worker image image: Visual Studio 2015 -# Build Configurations: dll/static, regular/debug +# Build Configurations: shared/static, optimized/debug configuration: - - dynamic + - default - static - - dynamic-debug + - debug - static-debug # Environment variables: compiler toolchain, base version, setup file, ... @@ -74,7 +74,7 @@ environment: - CMP: vs2019 SET: test00 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - - CMP: mingw + - CMP: gcc - CMP: vs2019 VV: 0 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -111,7 +111,7 @@ matrix: SET: test00 - configuration: static SET: test00 - - configuration: dynamic-debug + - configuration: debug SET: test00 - configuration: static-debug SET: test00 @@ -130,7 +130,7 @@ for: only: - SET: test00 build_script: - - cmd: python appveyor-test.py + - cmd: python cue-test.py test_script: - cmd: echo Tests have been run in the build phase @@ -139,11 +139,12 @@ for: #---------------------------------# build_script: - - cmd: python appveyor/do.py prepare - - cmd: python appveyor/do.py build + - cmd: python cue.py prepare + - cmd: python cue.py build test_script: - - cmd: python appveyor/do.py test + - cmd: python cue.py test + - cmd: python cue.py test-results #---------------------------------# # debugging # From c53bfa090e87d8d381f28a00afbd8cac5e2a9f54 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 14:32:27 +0200 Subject: [PATCH 38/55] cue: recompile all dependency modules after a cache-miss --- cue.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cue.py b/cue.py index 7d93301..c3cfe33 100644 --- a/cue.py +++ b/cue.py @@ -78,6 +78,7 @@ is_base314 = False is_make3 = False has_test_results = False silent_dep_builds = True +do_recompile = False def clear_lists(): @@ -90,6 +91,7 @@ def clear_lists(): is_make3 = False has_test_results = False silent_dep_builds = True + do_recompile = False ci['service'] = '' ci['os'] = '' ci['platform'] = '' @@ -380,6 +382,7 @@ def complete_setup(dep): # - Add $dep_VARNAME line to the RELEASE.local file in the cache area (unless already there) # - Add full path to $modules_to_compile def add_dependency(dep): + global do_recompile recurse = setup[dep + '_RECURSIVE'].lower() if recurse not in ['0', 'no']: recursearg = ["--recursive"] @@ -434,7 +437,8 @@ def add_dependency(dep): cwd=cachedir) sp.check_call(['git', 'log', '-n1'], cwd=place) - modules_to_compile.append(dep) + logger.debug('Setting do_recompile = True (all following modules will be recompiled') + do_recompile = True if dep == 'BASE': # add MSI 1.7 to Base 3.14 @@ -468,6 +472,8 @@ def add_dependency(dep): print(head, file=fout) fout.close() + if do_recompile: + modules_to_compile.append(dep) update_release_local(setup[dep + "_VARNAME"], place) From d4d094e2bb4b967a25a0cfff61f14b482f37cc31 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 15:53:09 +0200 Subject: [PATCH 39/55] cue-test: add DetectContext tests for AppVeyor --- cue-test.py | 192 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 181 insertions(+), 11 deletions(-) diff --git a/cue-test.py b/cue-test.py index e576a8d..9f0d241 100644 --- a/cue-test.py +++ b/cue-test.py @@ -331,12 +331,13 @@ class TestVCVars(unittest.TestCase): cue.with_vcvars('env') -class TestDetectContext(unittest.TestCase): +@unittest.skipIf(ci_service != 'travis', 'Run travis tests only on travis') +class TestTravisDetectContext(unittest.TestCase): def tearDown(self): cue.clear_lists() os.environ.pop('BCFG', None) - def test_TravisLinuxGccNone(self): + def test_LinuxGccNone(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -355,7 +356,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: shared-optimized)" .format(cue.ci['configuration'])) - def test_TravisLinuxClangNone(self): + def test_LinuxClangNone(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'clang' @@ -374,7 +375,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: shared-optimized)" .format(cue.ci['configuration'])) - def test_TravisBcfgShared(self): + def test_BcfgShared(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -386,7 +387,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: shared-optimized)" .format(cue.ci['configuration'])) - def test_TravisBcfgStatic(self): + def test_BcfgStatic(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -398,7 +399,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: static-optimized)" .format(cue.ci['configuration'])) - def test_TravisBcfgDebug(self): + def test_BcfgDebug(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -410,7 +411,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: shared-debug)" .format(cue.ci['configuration'])) - def test_TravisBcfgStaticDebug(self): + def test_BcfgStaticDebug(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -422,7 +423,7 @@ class TestDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: static-debug)" .format(cue.ci['configuration'])) - def test_TravisWindowsGccNone(self): + def test_WindowsGccNone(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' os.environ['TRAVIS_COMPILER'] = 'gcc' @@ -443,7 +444,7 @@ class TestDetectContext(unittest.TestCase): self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") - def test_TravisWindowsVs2017None(self): + def test_WindowsVs2017None(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' os.environ['TRAVIS_COMPILER'] = 'vs2017' @@ -464,7 +465,7 @@ class TestDetectContext(unittest.TestCase): self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") - def test_TravisWindowsVs2019None(self): + def test_WindowsVs2019None(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' os.environ['TRAVIS_COMPILER'] = 'vs2019' @@ -485,7 +486,7 @@ class TestDetectContext(unittest.TestCase): self.assertIn('strawberryperl', cue.ci['choco'], "'strawberryperl' is not in ci['choco']") self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") - def test_TravisOsxClangNone(self): + def test_OsxClangNone(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'osx' os.environ['TRAVIS_COMPILER'] = 'clang' @@ -505,6 +506,175 @@ class TestDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) +@unittest.skipIf(ci_service != 'appveyor', 'Run appveyor tests only on appveyor') +class TestAppveyorDetectContext(unittest.TestCase): + def tearDown(self): + cue.clear_lists() + os.environ.pop('CONFIGURATION', None) + + def test_Platform32(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x86' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertEqual(cue.ci['platform'], 'x86', + "ci['platform'] is {0} (expected: x86)" + .format(cue.ci['platform'])) + + def test_Platform64(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x64' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertEqual(cue.ci['platform'], 'x64', + "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + + def test_PlatformX64(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'X64' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertEqual(cue.ci['platform'], 'x64', + "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + + def test_ConfigDefault(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['CONFIGURATION'] = 'default' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + + def test_ConfigStatic(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['CONFIGURATION'] = 'static' + cue.detect_context() + self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'static-optimized', + "ci['configuration'] is {0} (expected: static-optimized)" + .format(cue.ci['configuration'])) + + def test_ConfigDebug(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['CONFIGURATION'] = 'debug' + cue.detect_context() + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertTrue(cue.ci['debug'], "ci['debug'] is False (expected: True)") + self.assertEqual(cue.ci['configuration'], 'shared-debug', + "ci['configuration'] is {0} (expected: shared-debug)" + .format(cue.ci['configuration'])) + + def test_ConfigStaticDebug(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['CONFIGURATION'] = 'static-debug' + cue.detect_context() + self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") + self.assertTrue(cue.ci['debug'], "ci['debug'] is False (expected: True)") + self.assertEqual(cue.ci['configuration'], 'static-debug', + "ci['configuration'] is {0} (expected: static-debug)" + .format(cue.ci['configuration'])) + + def test_WindowsGccNone(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x64' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'gcc', "ci['compiler'] is {0} (expected: gcc)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + def test_WindowsVs2017None(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2017' + os.environ['CMP'] = 'vs2017' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x86' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'vs2017', "ci['compiler'] is {0} (expected: vs2017)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x86', "ci['platform'] is {0} (expected: x86)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + def test_WindowsVs2019None(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x64' + cue.detect_context() + self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" + .format(cue.ci['service'])) + self.assertEqual(cue.ci['os'], 'windows', "ci['os'] is {0} (expected: windows)" + .format(cue.ci['os'])) + self.assertEqual(cue.ci['compiler'], 'vs2019', "ci['compiler'] is {0} (expected: vs2019)" + .format(cue.ci['compiler'])) + self.assertEqual(cue.ci['platform'], 'x64', "ci['platform'] is {0} (expected: x64)" + .format(cue.ci['platform'])) + self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") + self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") + self.assertEqual(cue.ci['configuration'], 'shared-optimized', + "ci['configuration'] is {0} (expected: shared-optimized)" + .format(cue.ci['configuration'])) + self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + + class TestSetupForBuild(unittest.TestCase): args = Namespace(paths=[]) cue.building_base = True From e4dd66fd5cb77a83764090b9e3d3e7c429692989 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Sat, 6 Jun 2020 16:01:32 +0200 Subject: [PATCH 40/55] cue-test: fix tests on AppVeyor (set CONFIGURATION) --- cue-test.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cue-test.py b/cue-test.py index 9f0d241..0dfd5f9 100644 --- a/cue-test.py +++ b/cue-test.py @@ -321,13 +321,12 @@ class TestDefaultModuleURLs(unittest.TestCase): self.assertEqual(repo_access(mod), 0, 'Defaults for {0} do not point to a valid git repository at {1}' .format(mod, cue.setup[mod + '_REPOURL'])) - +@unittest.skipIf(ci_os != 'windows', 'VCVars test only applies to windows') class TestVCVars(unittest.TestCase): def test_vcvars(self): - if ('CMP' in os.environ and os.environ['CMP'] in ('mingw',)) \ - or distutils.util.get_platform() != "win32": - raise unittest.SkipTest() - + if ci_service == 'appveyor': + os.environ['CONFIGURATION'] = 'default' + cue.detect_context() cue.with_vcvars('env') @@ -684,6 +683,8 @@ class TestSetupForBuild(unittest.TestCase): def setUp(self): os.environ.pop('EPICS_HOST_ARCH', None) cue.clear_lists() + if ci_service == 'appveyor': + os.environ['CONFIGURATION'] = 'default' cue.detect_context() def tearDown(self): From 2ea3e36eda63dbfdb1f96f784724e104aa2df5fa Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 12 Jun 2020 17:59:56 +0200 Subject: [PATCH 41/55] travis: remove bash scripts (v2.x implementation) --- travis/Add-RTEMS-pc368-qemu-target.patch | 77 ------- travis/build.sh | 48 ----- travis/prepare.sh | 247 ----------------------- travis/utils.sh | 218 -------------------- 4 files changed, 590 deletions(-) delete mode 100644 travis/Add-RTEMS-pc368-qemu-target.patch delete mode 100755 travis/build.sh delete mode 100755 travis/prepare.sh delete mode 100644 travis/utils.sh diff --git a/travis/Add-RTEMS-pc368-qemu-target.patch b/travis/Add-RTEMS-pc368-qemu-target.patch deleted file mode 100644 index de38660..0000000 --- a/travis/Add-RTEMS-pc368-qemu-target.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 00ee7bf7d3618c748491c88742c011a8353abeba Mon Sep 17 00:00:00 2001 -From: Andrew Johnson -Date: Wed, 24 Oct 2018 14:27:15 -0500 -Subject: [PATCH] Add RTEMS-pc368-qemu target, use in Travis-CI builds - ---- - configure/os/CONFIG.Common.RTEMS-pc386-qemu | 11 +++++++++++ - configure/os/CONFIG_SITE.Common.RTEMS-pc386 | 5 ----- - configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu | 9 +++++++++ - src/libCom/RTEMS/Makefile | 2 +- - src/tools/makeTestfile.pl | 2 +- - 6 files changed, 24 insertions(+), 10 deletions(-) - create mode 100644 configure/os/CONFIG.Common.RTEMS-pc386-qemu - delete mode 100644 configure/os/CONFIG_SITE.Common.RTEMS-pc386 - create mode 100644 configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu - -diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu -new file mode 100644 -index 000000000..684f01a19 ---- /dev/null -+++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu -@@ -0,0 +1,11 @@ -+# CONFIG.Common.RTEMS-pc386-qemu -+# -+# Definitions for the RTEMS-pc386-qemu target -+# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc386-qemu -+# -+#------------------------------------------------------- -+ -+# Include definitions from RTEMS-pc386 -+include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386 -+ -+RTEMS_QEMU_FIXUPS = YES -diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu -new file mode 100644 -index 000000000..027dcf4ab ---- /dev/null -+++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu -@@ -0,0 +1,9 @@ -+# CONFIG_SITE.Common.RTEMS-pc386-qemu -+# -+# Site-specific overrides for the RTEMS-pc386-qemu target -+# -+ -+# If you're building this architecture you _probably_ want to -+# run the tests for it under QEMU, but if not you can turn -+# them off here by commenting out this line: -+CROSS_COMPILER_RUNTEST_ARCHS += RTEMS-pc386-qemu -diff --git a/src/libCom/RTEMS/Makefile b/src/libCom/RTEMS/Makefile -index 2f12b7bf0..22a92733c 100644 ---- a/src/libCom/RTEMS/Makefile -+++ b/src/libCom/RTEMS/Makefile -@@ -24,7 +24,7 @@ rtemsCom_SRCS += epicsRtemsInitHookPre.c - rtemsCom_SRCS += epicsRtemsInitHookPost.c - rtemsCom_SRCS += epicsMemFs.c - --ifeq ($(T_A),RTEMS-pc386) -+ifeq ($(RTEMS_BSP),pc386) - rtemsCom_SRCS += ne2kpci.c - endif - -diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl -index 73f522034..fb431fe7a 100644 ---- a/src/tools/makeTestfile.pl -+++ b/src/tools/makeTestfile.pl -@@ -37,7 +37,7 @@ if( $TA =~ /^win32-x86/ && $HA !~ /^win/ ) { - $exec = "wine64 $exe"; - - # Run pc386 test harness w/ QEMU --} elsif( $TA =~ /^RTEMS-pc386$/ ) { -+} elsif( $TA =~ /^RTEMS-pc386-qemu$/ ) { - $exec = "qemu-system-i386 -m 64 -no-reboot -serial stdio -display none -net nic,model=ne2k_pci -net user,restrict=yes -kernel $exe"; - - # Explicitly fail for other RTEMS targets --- -2.21.0.windows.1 - diff --git a/travis/build.sh b/travis/build.sh deleted file mode 100755 index f282614..0000000 --- a/travis/build.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -set -e - -# Set VV in .travis.yml to make scripts verbose -[ "$VV" ] && set -x - -CURDIR="$PWD" -CACHEDIR=${CACHEDIR:-${HOME}/.cache} - -if [ "$BASE" = "SELF" ] -then - EPICS_BASE=$CURDIR -else - eval $(grep "EPICS_BASE=" ${CACHEDIR}/RELEASE.local) -fi -export EPICS_BASE - -[ -z "$EPICS_HOST_ARCH" -a -f $EPICS_BASE/src/tools/EpicsHostArch.pl ] && EPICS_HOST_ARCH=$(perl $EPICS_BASE/src/tools/EpicsHostArch.pl) -[ -z "$EPICS_HOST_ARCH" -a -f $EPICS_BASE/startup/EpicsHostArch.pl ] && EPICS_HOST_ARCH=$(perl $EPICS_BASE/startup/EpicsHostArch.pl) -export EPICS_HOST_ARCH - -# Base 3.15 doesn't have -qemu target architecture and needs an extra define -[ -e $EPICS_BASE/configure/os/CONFIG.Common.RTEMS-pc386-qemu ] || EXTRA_QEMU=RTEMS_QEMU_FIXUPS=YES - -# use array variable to get the quoting right while using separate words for arguments -[ -n "$EXTRA0" ] && EXTRA[0]="$EXTRA0" -[ -n "$EXTRA1" ] && EXTRA[1]="$EXTRA1" -[ -n "$EXTRA2" ] && EXTRA[2]="$EXTRA2" -[ -n "$EXTRA3" ] && EXTRA[3]="$EXTRA3" -[ -n "$EXTRA4" ] && EXTRA[4]="$EXTRA4" -[ -n "$EXTRA5" ] && EXTRA[5]="$EXTRA5" - -make -j2 $EXTRA_QEMU "${EXTRA[@]}" - -ret=0 - -if [ "$TEST" != "NO" ] -then - if grep -q "BASE_3_14\s*=\s*NO" $EPICS_BASE/configure/CONFIG_BASE_VERSION && grep -q "^test-results:" $EPICS_BASE/configure/RULES_BUILD - then - make -j2 tapfiles || ret=$? - make -sk test-results - else - make runtests - fi -fi - -exit $ret diff --git a/travis/prepare.sh b/travis/prepare.sh deleted file mode 100755 index e313384..0000000 --- a/travis/prepare.sh +++ /dev/null @@ -1,247 +0,0 @@ -#!/bin/bash -set -e - -# The following if clause can be removed for ci-scripts major version 3 -if [ "$TRAVIS_OS_NAME" == osx -a "$BASH_VERSINFO" -lt 4 ] -then - brew install bash - if [ $(/usr/local/bin/bash -c 'echo $BASH_VERSINFO') -lt 4 ] - then - echo "Failed to install a recent bash" >&2 - exit 1 - fi - exec /usr/local/bin/bash $0 "$@" -fi - -# Set VV in .travis.yml to make scripts verbose -[ "$VV" ] && set -x - -# Perl version of "readlink -f" (which MacOS does not provide) -readlinkf() { perl -MCwd -e 'print Cwd::abs_path shift' "$1"; } - -SCRIPTDIR=$(dirname $(readlinkf $0)) -CURDIR="$PWD" -CACHEDIR=${CACHEDIR:-${HOME}/.cache} -[ -e ${CACHEDIR} ] || mkdir -p ${CACHEDIR} - -# source functions -. $SCRIPTDIR/utils.sh - -echo -e "${ANSI_YELLOW}Using bash version $BASH_VERSION${ANSI_RESET}" - -if [ -f /etc/hosts ] -then - # The travis-ci "bionic" image throws us a curveball in /etc/hosts - # by including two entries for localhost. The first for 127.0.1.1 - # which causes epicsSockResolveTest to fail. - # cat /etc/hosts - # ... - # 127.0.1.1 localhost localhost ip4-loopback - # 127.0.0.1 localhost nettuno travis vagrant travis-job-.... - - sudo sed -i -e '/^127\.0\.1\.1/ s|localhost\s*||g' /etc/hosts - - echo "==== /etc/hosts" - cat /etc/hosts - echo "====" -fi - -# Load settings -# ------------- - -fold_start load.settings "Loading settings" - -# load default settings for well-known modules -source_set defaults - -# source configured settings -[ -z "${SET+x}" ] || source_set $SET - -fold_end load.settings - -# Check out dependencies -# ---------------------- - -if [ "$BASE" != "SELF" ] -then - fold_start check.out.dependencies "Checking/cloning dependencies" - - for mod in BASE $ADD_MODULES $MODULES - do - mod_uc=${mod^^} - eval add_dependency $mod_uc \${${mod_uc}:=master} - done - [ -d ./configure ] && target=./configure/RELEASE.local || target=./RELEASE.local - cp ${CACHEDIR}/RELEASE.local $target - - fold_end check.out.dependencies -fi - -# Set up compiler -# --------------- - -fold_start set.up.epics_build "Setting up EPICS build system" - -if [ "$BASE" = "SELF" ] -then - EPICS_BASE=$CURDIR -else - eval $(grep "EPICS_BASE=" ${CACHEDIR}/RELEASE.local) -fi -export EPICS_BASE -echo "EPICS_BASE=$EPICS_BASE" - -[ -z "$EPICS_HOST_ARCH" -a -f $EPICS_BASE/src/tools/EpicsHostArch.pl ] && EPICS_HOST_ARCH=$(perl $EPICS_BASE/src/tools/EpicsHostArch.pl) -[ -z "$EPICS_HOST_ARCH" -a -f $EPICS_BASE/startup/EpicsHostArch.pl ] && EPICS_HOST_ARCH=$(perl $EPICS_BASE/startup/EpicsHostArch.pl) -export EPICS_HOST_ARCH -echo "EPICS_HOST_ARCH=$EPICS_HOST_ARCH" - -if echo ${modules_to_compile} | grep -q "$EPICS_BASE" || [ "$BASE" = "SELF" ] -then - - # requires wine and g++-mingw-w64-i686 - if [ "$WINE" = "32" ] - then - echo "Cross mingw32" - sed -i -e '/CMPLR_PREFIX/d' $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw - cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw -CMPLR_PREFIX=i686-w64-mingw32- -EOF - cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE -CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw -EOF - - elif [ "$WINE" = "64" ] - then - echo "Cross mingw64" - sed -i -e '/CMPLR_PREFIX/d' $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.windows-x64-mingw - cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.windows-x64-mingw -CMPLR_PREFIX=x86_64-w64-mingw32- -EOF - cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE -CROSS_COMPILER_TARGET_ARCHS+=windows-x64-mingw -EOF - fi - - if [ "$STATIC" = "YES" ] - then - echo "Build static libraries/executables" - cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE -SHARED_LIBRARIES=NO -STATIC_BUILD=YES -EOF - fi - - HOST_CCMPLR_NAME=`echo "$TRAVIS_COMPILER" | sed -E 's/^([[:alpha:]][^-]*(-[[:alpha:]][^-]*)*)+(-[0-9\.]+)?$/\1/g'` - HOST_CMPLR_VER_SUFFIX=`echo "$TRAVIS_COMPILER" | sed -E 's/^([[:alpha:]][^-]*(-[[:alpha:]][^-]*)*)+(-[0-9\.]+)?$/\3/g'` - HOST_CMPLR_VER=`echo "$HOST_CMPLR_VER_SUFFIX" | cut -c 2-` - - case "$HOST_CCMPLR_NAME" in - clang) - echo "Host compiler is clang" - HOST_CPPCMPLR_NAME=$(echo "$HOST_CCMPLR_NAME" | sed 's/clang/clang++/g') - cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH -GNU = NO -CMPLR_CLASS = clang -CC = ${HOST_CCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX -CCC = ${HOST_CPPCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX -EOF - - # hack - sed -i -e 's/CMPLR_CLASS = gcc/CMPLR_CLASS = clang/' $EPICS_BASE/configure/CONFIG.gnuCommon - - ${HOST_CCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX --version - ;; - gcc) - echo "Host compiler is GCC" - HOST_CPPCMPLR_NAME=$(echo "$HOST_CCMPLR_NAME" | sed 's/gcc/g++/g') - cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH -CC = ${HOST_CCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX -CCC = ${HOST_CPPCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX -EOF - - ${HOST_CCMPLR_NAME}$HOST_CMPLR_VER_SUFFIX --version - ;; - *) - echo "Host compiler is default" - gcc --version - ;; - esac - - cat <> $EPICS_BASE/configure/CONFIG_SITE -USR_CPPFLAGS += $USR_CPPFLAGS -USR_CFLAGS += $USR_CFLAGS -USR_CXXFLAGS += $USR_CXXFLAGS -EOF - - # set RTEMS to eg. "4.9" or "4.10" - # requires qemu, bison, flex, texinfo, install-info - if [ -n "$RTEMS" ] - then - echo "Cross RTEMS${RTEMS} for pc386" - sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' $EPICS_BASE/configure/os/CONFIG_SITE.Common.RTEMS - cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.Common.RTEMS -RTEMS_VERSION=$RTEMS -RTEMS_BASE=$HOME/.rtems -EOF - # Base 3.15 doesn't have -qemu target architecture - [ -e $EPICS_BASE/configure/os/CONFIG.Common.RTEMS-pc386-qemu ] && QEMU=-qemu - cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE -CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386$QEMU -EOF - fi - -else - echo -e "${ANSI_GREEN}EPICS build system already set up (Base was loaded from cache)${ANSI_RESET}" -fi - -# Download RTEMS cross compiler -if [ -n "$RTEMS" ] -then - echo "Downloading RTEMS${RTEMS} cross compiler for pc386" - curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \ - | tar -C / -xmj -fi - -fold_end set.up.compiler - -echo "\$ make --version" -make --version - -[ "$BASE" = "SELF" ] && exit 0 - -# Build required dependencies -# --------------------------- - -fold_start build.dependencies "Build missing/outdated dependencies" - -[ "$VV" ] && silent="-s" || silent= - -[ -z "$modules_to_compile" ] && echo -e "${ANSI_GREEN}All dependency modules are up-to-date (nothing to do)${ANSI_RESET}" - -for module in ${modules_to_compile} -do - eval name=\${module#${CACHEDIR}/} - fold_start build.$name "Build $name" - make -j2 $silent -C $module $EXTRA - fold_end build.$name -done - -fold_end build.dependencies - -echo -e "${ANSI_BLUE}Dependency module information${ANSI_RESET}" - -echo "Module Tag Binaries Commit" -echo "-----------------------------------------------------------------------------------" -for mod in base $MODULES $ADD_MODULES -do - mod_uc=${mod^^} - eval tag=\${${mod_uc}} - eval dir=${CACHEDIR}/\${${mod_uc}_DIRNAME}-$tag - echo "$modules_to_compile" | grep -q "$dir" && stat="rebuilt" || stat="from cache" - commit=$(git -C $dir log -n1 --oneline) - printf "%-10s %-12s %-11s %s\n" "$mod" "$tag" "$stat" "$commit" -done - -echo -e "${ANSI_BLUE}Contents of RELEASE.local${ANSI_RESET}" -cat ${CACHEDIR}/RELEASE.local diff --git a/travis/utils.sh b/travis/utils.sh deleted file mode 100644 index 822e933..0000000 --- a/travis/utils.sh +++ /dev/null @@ -1,218 +0,0 @@ -# Utility functions for Travis scripts in ci-scripts -# -# This file is sourced by the executable scripts -# CACHEDIR must be defined and existing before calling these functions - -# Portable version of 'sed -i' (that MacOS doesn't provide) - -# sedi (cmd, file) -# Do the equivalent of "sed -i cmd file" -sedi () { - cat $2 | sed "$1" > $2.tmp$$; mv -f $2.tmp$$ $2 -} - -# Setup ANSI Colors -export ANSI_RED="\033[31;1m" -export ANSI_GREEN="\033[32;1m" -export ANSI_YELLOW="\033[33;1m" -export ANSI_BLUE="\033[34;1m" -export ANSI_RESET="\033[0m" -export ANSI_CLEAR="\033[0K" - -# Travis log fold control -# from https://github.com/travis-ci/travis-rubies/blob/build/build.sh - -fold_start() { - echo -e "travis_fold:start:$1\\r${ANSI_YELLOW}$2${ANSI_RESET}" -} - -fold_end() { - echo -en "travis_fold:end:$1\\r" -} - -die() { - echo -e "${ANSI_RED}$1${ANSI_RESET}" - [ "$UTILS_UNITTEST" ] || exit 1 -} - -# source_set(settings) -# -# Source a settings file (extension .set) found in SETUP_PATH -# May be called recursively (from within a settings file) -declare -a SEEN_SETUPS -source_set() { - local set_file=${1//[$'\r']} - local set_dir - local found=0 - [ "${SETUP_PATH}" ] || die "Search path for setup files (SETUP_PATH) is empty" - for set_dir in ${SETUP_PATH//:/ } - do - if [ -e $set_dir/$set_file.set ] - then - if [[ " ${SEEN_SETUPS[@]} " =~ " $set_dir/$set_file.set " ]] - then - echo "Ignoring already included setup file $set_dir/$set_file.set" - return - fi - SEEN_SETUPS+=($set_dir/$set_file.set) - echo "Loading setup file $set_dir/$set_file.set" - local line - while read -r line - do - [ -z "$line" ] && continue - echo $line | grep -q "^#" && continue - if echo $line | grep -q "^include\W" - then - source_set $(echo $line | awk '{ print $2 }') - continue - fi - if echo "$line" | grep -q "^\w\+=" - then - IFS== read var value <<< "${line//[$'\r']}" - value=$(sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<< "$value") # remove surrounding quotes - eval [ "\${$var}" ] || eval "$var=\$value" - fi - done < $set_dir/$set_file.set - found=1 - break - fi - done - [ $found -ne 0 ] || die "Setup file $set_file.set does not exist in SETUP_PATH search path ($SETUP_PATH)" -} - -# update_release_local(varname, place) -# varname name of the variable to set in RELEASE.local -# place place (absolute path) of where variable should point to -# -# Manipulate RELEASE.local in the cache location: -# - replace "$varname=$place" line if it exists and has changed -# - otherwise add "$varname=$place" line and possibly move EPICS_BASE=... line to the end -update_release_local() { - local var=$1 - local place=$2 - local release_local=${CACHEDIR}/RELEASE.local - local updated_line="${var}=${place}" - - local ret=0 - [ -e ${release_local} ] && grep -q "${var}=" ${release_local} || ret=$? - if [ $ret -eq 0 ] - then - existing_line=$(grep "${var}=" ${release_local}) - if [ "${existing_line}" != "${updated_line}" ] - then - sedi "s|${var}=.*|${var}=${place}|g" ${release_local} - fi - else - echo "$var=$place" >> ${release_local} - ret=0 - grep -q "EPICS_BASE=" ${release_local} || ret=$? - if [ $ret -eq 0 ] - then - base_line=$(grep "EPICS_BASE=" ${release_local}) - sedi '\|EPICS_BASE=|d' ${release_local} - echo ${base_line} >> ${release_local} - fi - fi -} - -# add_dependency(dep, tag) -# -# Add a dependency to the cache area: -# - check out (recursive if configured) in the CACHE area unless it already exists and the -# required commit has been built -# - Defaults: -# $dep_DIRNAME = lower case ($dep) -# $dep_REPONAME = lower case ($dep) -# $dep_REPOURL = GitHub / $dep_REPOOWNER (or $REPOOWNER or epics-modules) / $dep_REPONAME .git -# $dep_VARNAME = $dep -# $dep_DEPTH = 5 -# $dep_RECURSIVE = 1/YES (0/NO to for a flat clone) -# - Add $dep_VARNAME line to the RELEASE.local file in the cache area (unless already there) -# - Add full path to $modules_to_compile -add_dependency() { - curdir="$PWD" - DEP=$1 - TAG=$2 - dep_lc=${DEP,,} - eval dirname=\${${DEP}_DIRNAME:=${dep_lc}} - eval reponame=\${${DEP}_REPONAME:=${dep_lc}} - eval repourl=\${${DEP}_REPOURL:="https://github.com/\${${DEP}_REPOOWNER:=${REPOOWNER:-epics-modules}}/${reponame}.git"} - eval varname=\${${DEP}_VARNAME:=${DEP}} - eval recursive=\${${DEP}_RECURSIVE:=1} - recursive=${recursive,,} - local recurse="" - [ "$recursive" != "0" -a "$recursive" != "no" ] && recurse="--recursive" - - # determine if $DEP points to a valid release or branch - git ls-remote --quiet --exit-code --refs $repourl "$TAG" > /dev/null 2>&1 || - die "$TAG is neither a tag nor a branch name for $DEP ($repourl)" - - if [ -e $CACHEDIR/$dirname-$TAG ] - then - [ -e $CACHEDIR/$dirname-$TAG/built ] && BUILT=$(cat $CACHEDIR/$dirname-$TAG/built) || BUILT="never" - HEAD=$(cd "$CACHEDIR/$dirname-$TAG" && git log -n1 --pretty=format:%H) - if [ "$HEAD" != "$BUILT" ] - then - rm -fr $CACHEDIR/$dirname-$TAG - else - echo "Found $TAG of dependency $DEP in $CACHEDIR/$dirname-$TAG" - fi - fi - - if [ ! -e $CACHEDIR/$dirname-$TAG ] - then - cd $CACHEDIR - eval depth=\${${DEP}_DEPTH:-"-1"} - case ${depth} in - -1 ) - deptharg="--depth 5" - ;; - 0 ) - deptharg="" - ;; - * ) - deptharg="--depth $depth" - ;; - esac - echo "Cloning $TAG of dependency $DEP into $CACHEDIR/$dirname-$TAG" - git clone --quiet $deptharg $recurse --branch "$TAG" $repourl $dirname-$TAG - ( cd $dirname-$TAG && git log -n1 ) - do_recompile=yes - # add MSI to Base 3.14 - if [ $DEP == "BASE" ] - then - versionfile=$CACHEDIR/$dirname-$TAG/configure/CONFIG_BASE_VERSION - if [ -e ${versionfile} ] && grep -q "BASE_3_14=YES" ${versionfile} - then - echo "Adding MSI 1.7 to $CACHEDIR/$dirname-$TAG" - ( cd $dirname-$TAG; patch -p1 < $SCRIPTDIR/../add-msi-to-314.patch ) - fi - else - # fix non-base modules that do not include the .local files in configure/RELEASE - release=$CACHEDIR/$dirname-$TAG/configure/RELEASE - if [ -e $release ] - then - echo "-include \$(TOP)/../RELEASE.local" > $release - fi - fi - # run hook - eval hook="\${${DEP}_HOOK}" - if [ "$hook" ] - then - if [ -x "$curdir/$hook" ] - then - echo "Running hook $hook in $CACHEDIR/$dirname-$TAG" - ( cd $CACHEDIR/$dirname-$TAG; "$curdir/$hook" ) - else - die "Hook script $hook is not executable or does not exist." - fi - fi - HEAD=$(cd "$CACHEDIR/$dirname-$TAG" && git log -n1 --pretty=format:%H) - echo "$HEAD" > "$CACHEDIR/$dirname-$TAG/built" - cd "$curdir" - fi - - [ "${do_recompile}" ] && modules_to_compile="${modules_to_compile} $CACHEDIR/$dirname-$TAG" - - update_release_local ${varname} $CACHEDIR/$dirname-$TAG -} From e867277f6e4a8cb982739167997c8648a3d1bcba Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 8 Jun 2020 10:26:17 +0200 Subject: [PATCH 42/55] Update README files for v3.0 --- README.md | 65 ++++++++++++++++++++++++++++++---------------- appveyor/README.md | 23 +++++++++------- travis/README.md | 10 ++++--- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 507d6e9..8627062 100644 --- a/README.md +++ b/README.md @@ -20,58 +20,70 @@ never break existing use. ## This Repository -In addition to the scripts themselves (in the subdirectories), -this repository contains the test suite that is used to verify -functionality and features of the ci-scripts. +In addition to the script that runs the builds and tests, this repository +contains service specific documentation and example configuration files +(in the subdirectories), and a small test suite that is used to verify +functionality and features of the ci-scripts module itself You are welcome to use the test suite as a reference, but keep in -mind that in your module the path to the scripts has one level more -(e.g., `./travis/abc` here would be `./.ci/travis/abc` in your +mind that in your main module the path to the scripts has one level more +(e.g., `./abc` here would be `./.ci/abc` in your module). -Also, a test suite might not show the same level of quality as an -example. +Also, a test suite might not show the same quality and documentation levels +as an example. ## Features - Compile against different branches or releases of EPICS Base and - additional dependencies (modules like asyn, std, etc.). + additional dependencies (modules like asyn, std, sequencer, etc.). - Define settings files that declare sets of dependencies with their versions and locations. - - Define hook scripts for any dependency. + - Define hooks for any dependency. Hooks are run on the dependency module before it is compiled, so the module can be patched or further configured. - - Define static or shared builds (executables, libraries). + - Define shared (default) or static builds (for executables and libraries). + + - Define optimized (default) or debug builds. - - Run tests (using the EPICS unit test suite). + - Run tests (using the EPICS build system, i.e., `make runtests` + and friends). ## Supported CI Services ### [Travis-CI](https://travis-ci.org/) + - Five parallel runners on Linux/Windows (one runner on MacOS) - Use different compilers (gcc, clang) - Use different gcc versions - Cross-compile for Windows 32bit and 64bit using MinGW and WINE - - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.16.2) - - Compile on MacOS - - Built dependencies are cached (for faster builds) + - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15) + - Compile natively on MacOS (clang) + - Compile natively on Windows (gcc/MinGW, Visual Studio 2017) + - Built dependencies are cached (for faster builds). -See specific **[ci-scripts on Travis-CI README](travis/README.md)** for more details. +See specific +**[ci-scripts on Travis-CI README](travis/README.md)** +for more details. ### [AppVeyor](https://www.appveyor.com/) - - Use different compilers (Visual Studio, MinGW) + - One parallel runner (all builds are sequential) + - Use different compilers (Visual Studio, gcc/MinGW) - Use different Visual Studio versions: \ - 2008, 2010, 2012, 2013, 2015, 2017, 2019 + 2008, 2010, 2012, 2013, 2015, 2017, 2019 - Compile for Windows 32bit and 64bit + - No useful caching available. -See specific **[ci-scripts on AppVeyor README](appveyor/README.md)** for more details. +See specific +**[ci-scripts on AppVeyor README](appveyor/README.md)** +for more details. ## How to Use the CI-Scripts 1. Get an account on a supported CI service provider platform. (e.g. [Travis-CI](https://travis-ci.org/), - [AppVeyor](https://www.appveyor.com/), Azure Pipelines...) + [AppVeyor](https://www.appveyor.com/), ...) (More details in the specific README of the subdirectory.) @@ -94,8 +106,8 @@ See specific **[ci-scripts on AppVeyor README](appveyor/README.md)** for more de ``` will compile against the EPICS Base 3.15 branch, the Sequencer release 2.2.8 and release 4.34 of asyn. - (Any settings can be overridden from the specific job configuration - in e.g. `.travis.yml`.) + (Any settings can be overridden from the specific job line + in the service configuration, e.g., `.travis.yml`.) 4. Create a configuration for the CI service by copying one of the examples provided in the service specific subdirectory @@ -111,8 +123,8 @@ Your module might depend on EPICS Base and a few other support modules. (E.g., a specific driver might need StreamDevice, ASYN and the Sequencer.) In that case, building against every possible combination of released versions of those dependencies is not possible: -Base (37) x StreamDevice (50) x ASYN (40) x Sequencer (51) would produce -more than 3.7 million different combinations, i.e. build jobs. +Base (39) x StreamDevice (50) x ASYN (40) x Sequencer (52) would produce +more than 4 million different combinations, i.e. build jobs. A more reasonable approach is to create a few setups, each being a combination of dependency releases, that do a few scans of the available @@ -201,6 +213,13 @@ builds to higher verbosity. For debugging on your local machine, you may set `CACHEDIR` to change the location for the dependency builds. [default is `$HOME/.cache`] +Service specific debugging options are described in the README files +in the service specific subdirectories: + +- [Travis-CI README](travis/README.md) +- [AppVeyor README](appveyor/README.md) + + ## References: EPICS Modules Using ci-scripts [EPICS Base](https://github.com/epics-base/epics-base) and its submodules diff --git a/appveyor/README.md b/appveyor/README.md index 2ee6084..e4005f3 100644 --- a/appveyor/README.md +++ b/appveyor/README.md @@ -2,11 +2,12 @@ ## Features - - Use different compilers (Visual Studio, MinGW) - - Use different VS versions (2008, 2010, 2012, 2013, 2015, 2017, 2019) + - One parallel runner (all builds are sequential) + - Use different compilers (Visual Studio, gcc/MinGW) + - Use different Visual Studio versions: \ + 2008, 2010, 2012, 2013, 2015, 2017, 2019 - Compile for Windows 32bit and 64bit - - Create static libraries or DLLs (plus the matching executables) - - Create optimized or debug builds + - No useful caching available. ## How to Use these Scripts @@ -33,24 +34,26 @@ AppVeyor automatically creates a build matrix with the following axes: 1. `configuration:` \ - Select static or dynamic (DLL) as well as regular or debug builds. + Select shared (DLL) or static as well as optimized or debug builds. \ + Default: `shared-optimized` 2. `platform:` \ Select 32bit or 64bit processor architecture. 3. `environment: / matrix:` \ List of environment variable settings. Each list element (starting with a dash) is one step on the axis of the build matrix. \ - Set `CMP` to select the compiler: `mingw` for the native + Set `CMP` to select the compiler: `gcc` for the native [MinGW](http://mingw-w64.org/) GNU compiler, `vs2008` ...`vs2019` (options listed above) for the Microsoft Visual Studio compilers. Your builds will take long. \ - AppVeyor only grants a single worker VM - all jobs of the matrix are - executed sequentially. Each job will take between 6 and 15 minutes, - plus testing time. + AppVeyor only grants a single parallel runner VM - all jobs of the matrix + are executed sequentially. AppVeyor also does not provide a usable cache + mechanism to retain dependency artifacts across builds. + Each job will take between 6 and 15 minutes, plus testing time, every time. The `matrix: / exclude:` setting can be used to reduce the number of jobs. Check the [AppVeyor docs][appveyor.doc.matrix] - for more ways to reduce the build matrix size. + for more ways to reduce the build matrix size. \ E.g., you can opt for not creating matrix axes for `configuration:` and`platform:` by moving these configurations into the job lines under `environment: / matrix:`. diff --git a/travis/README.md b/travis/README.md index 1f4bcb0..2d9dac5 100644 --- a/travis/README.md +++ b/travis/README.md @@ -2,12 +2,14 @@ ## Features + - Five parallel runners on Linux/Windows (one runner on MacOS) - Use different compilers (gcc, clang) - Use different gcc versions - Cross-compile for Windows 32bit and 64bit using MinGW and WINE - - Cross-compile for RTEMS 4.9 and 4.10 - - Compile on MacOS - - Released versions of dependencies are cached (for faster builds) + - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15) + - Compile natively on MacOS (clang) + - Compile natively on Windows (gcc/MinGW, Visual Studio 2017) + - Built dependencies are cached (for faster builds). ## How to Use these Scripts @@ -34,7 +36,7 @@ Travis to run. Build jobs are declared in the list following the `jobs: include:` - declaration. Each element (starting with `-` in column 3) defines the + declaration. Each element (starting with a dash) defines the settings for one build job. `env:` controls the setting of environment variables,`dist:` specifies the Linux distribution, `os:` the operating system. From e3d6ee16a9ebe9b0740193da383f873fd422da4c Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 8 Jun 2020 11:28:51 +0200 Subject: [PATCH 43/55] travis: update examples for v3.0 --- travis/.travis.yml.example-full | 44 ++++++++++++++++++++------------- travis/.travis.yml.example-mini | 8 +++--- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/travis/.travis.yml.example-full b/travis/.travis.yml.example-full index 3485ceb..df5491c 100644 --- a/travis/.travis.yml.example-full +++ b/travis/.travis.yml.example-full @@ -14,6 +14,8 @@ cache: env: global: - SETUP_PATH=.ci-local:.ci + # for the sequencer on Windows + - CHOCO=re2c addons: apt: @@ -31,17 +33,17 @@ addons: - qemu-system-x86 homebrew: packages: - # for all EPICS builds - - bash # for the sequencer - re2c update: true install: - - ./.ci/travis/prepare.sh + - python .ci/cue.py prepare script: - - ./.ci/travis/build.sh + - python .ci/cue.py build + - python .ci/cue.py test + - python .ci/cue.py test-results # If you need to do more during install and build, # add a local directory to your module and do e.g. @@ -52,12 +54,13 @@ script: # Well-known variables to use # SET source setup file # ADD_MODULES extra modules (for a specific job) -# EXTRA content will be added to make command line -# EXTRA1..5 additional arguments for the make command -# (one argument per variable) -# STATIC set to YES for static build (default: NO) +# BCFG build configuration (static/debug/static-debug; +# default: shared-optimized) # TEST set to NO to skip running the tests (default: YES) # VV set to make build scripts verbose (default: unset) +# EXTRA content will be added to make command line +# EXTRA1..5 more additional arguments for the make command +# (one argument per variable) # Usually from setup files, but may be specified or overridden # on a job line @@ -76,7 +79,7 @@ jobs: - env: BASE=7.0 compiler: clang - - env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11" + - env: BASE=7.0 - env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11" compiler: clang @@ -89,19 +92,17 @@ jobs: - env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11" dist: trusty -# Cross-compilations to Windows using MinGW and WINE - - - env: BASE=7.0 WINE=32 TEST=NO STATIC=YES - compiler: mingw +# Cross-compilations to Windows using gcc/MinGW and WINE - - env: BASE=7.0 WINE=64 TEST=NO STATIC=NO - compiler: mingw + - env: BASE=7.0 WINE=32 TEST=NO BCFG=static + + - env: BASE=7.0 WINE=64 TEST=NO # Cross-compilation to RTEMS - - env: BASE=7.0 RTEMS=4.10 TEST=NO + - env: BASE=7.0 RTEMS=4.10 - - env: BASE=7.0 RTEMS=4.9 TEST=NO + - env: BASE=7.0 RTEMS=4.9 # Other gcc versions (added as an extra package) @@ -118,3 +119,12 @@ jobs: - env: BASE=7.0 os: osx compiler: clang + +# Windows builds + + - env: BASE=7.0 + os: windows + compiler: vs2017 + + - env: BASE=7.0 + os: windows diff --git a/travis/.travis.yml.example-mini b/travis/.travis.yml.example-mini index d680894..bede258 100644 --- a/travis/.travis.yml.example-mini +++ b/travis/.travis.yml.example-mini @@ -15,12 +15,14 @@ addons: - perl install: - - ./.ci/travis/prepare.sh + - python .ci/cue.py prepare script: - - ./.ci/travis/build.sh + - python .ci/cue.py build + - python .ci/cue.py test + - python .ci/cue.py test-results -# Build using default gcc for Base branches 7.0 and 3.15 +# Build on Linux using default gcc for Base branches 7.0 and 3.15 jobs: include: From 99619b5b9064b32e010cc814b64da0cea9887c2a Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 8 Jun 2020 11:28:56 +0200 Subject: [PATCH 44/55] appveyor: update examples for v3.0 --- appveyor/.appveyor.yml.example-full | 42 ++++++++++++++++++++++------- appveyor/.appveyor.yml.example-mini | 16 +++++------ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/appveyor/.appveyor.yml.example-full b/appveyor/.appveyor.yml.example-full index 8892f30..36b9e58 100644 --- a/appveyor/.appveyor.yml.example-full +++ b/appveyor/.appveyor.yml.example-full @@ -56,23 +56,45 @@ install: # Default build worker image image: Visual Studio 2015 -# Build Configurations: dll/static, regular/debug +# Build Configurations: shared/static, optimized/debug configuration: - - dynamic + - default - static - - dynamic-debug + - debug - static-debug -# Environment variables: compiler toolchain, base version, setup file, ... +# Environment variables + +# Well-known variables to use +# CMP compiler to use ('gcc' for native MinGW, 'vs...' for Visual Studio) +# SET source setup file +# ADD_MODULES extra modules (for a specific job) +# TEST set to NO to skip running the tests (default: YES) +# VV set VV=1 to make build scripts verbose (default: unset) +# EXTRA content will be added to make command line +# EXTRA1..5 more additional arguments for the make command +# (one argument per variable) + +# Usually from setup files, but may be specified or overridden +# on a job line +# MODULES list of dependency modules +# BASE branch or release tag name of the EPICS Base to use +# branch or release tag for a specific module +# ... see README for setup file syntax description + +# AppVeyor specific +# APPVEYOR_BUILD_WORKER_IMAGE run job using specified VM image +# (not the one from the image: line above) + environment: # common / default variables for all jobs SETUP_PATH: .ci-local:.ci + BASE: 7.0 matrix: - CMP: vs2019 - SET: test00 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - - CMP: mingw + - CMP: gcc - CMP: vs2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMP: vs2019 @@ -116,15 +138,15 @@ matrix: #---------------------------------# build_script: - - cmd: python .ci/appveyor/do.py prepare - - cmd: python .ci/appveyor/do.py build + - cmd: python .ci/cue.py prepare + - cmd: python .ci/cue.py build test_script: - - cmd: python .ci/appveyor/do.py test + - cmd: python .ci/cue.py test on_finish: - ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - - cmd: python .ci/appveyor/do.py build test-results -s + - cmd: python .ci/cue.py test-results #---------------------------------# # debugging # diff --git a/appveyor/.appveyor.yml.example-mini b/appveyor/.appveyor.yml.example-mini index bec8658..9bb41bc 100644 --- a/appveyor/.appveyor.yml.example-mini +++ b/appveyor/.appveyor.yml.example-mini @@ -1,8 +1,6 @@ # .appveyor.yml for use with EPICS Base ci-scripts # (see: https://github.com/epics-base/ci-scripts) -# This is YAML - indentation levels are crucial - cache: - C:\Users\appveyor\.tools @@ -24,11 +22,11 @@ install: image: Visual Studio 2019 -# Build Configurations: dll/static, regular/debug +# Build Configurations: shared/static, optimized/debug configuration: - - dynamic + - default # - static - - dynamic-debug + - debug # - static-debug environment: @@ -58,15 +56,15 @@ matrix: CMP: vs2008 build_script: - - cmd: python .ci/appveyor/do.py prepare - - cmd: python .ci/appveyor/do.py build + - cmd: python .ci/cue.py prepare + - cmd: python .ci/cue.py build test_script: - - cmd: python .ci/appveyor/do.py test + - cmd: python .ci/cue.py test on_finish: - ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - - cmd: python .ci/appveyor/do.py build test-results -s + - cmd: python .ci/cue.py test-results notifications: - provider: GitHubPullRequest From 590e0e4d263c985884c87757e72765f09419ed36 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 8 Jun 2020 11:42:07 +0200 Subject: [PATCH 45/55] cue: implement EXTRA..EXTRA5 to set additional make args; add test --- cue-test.py | 12 ++++++++++-- cue.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cue-test.py b/cue-test.py index 0dfd5f9..0561f25 100644 --- a/cue-test.py +++ b/cue-test.py @@ -681,8 +681,6 @@ class TestSetupForBuild(unittest.TestCase): sp.check_call(['choco', 'install', 'make']) def setUp(self): - os.environ.pop('EPICS_HOST_ARCH', None) - cue.clear_lists() if ci_service == 'appveyor': os.environ['CONFIGURATION'] = 'default' cue.detect_context() @@ -810,6 +808,16 @@ class TestSetupForBuild(unittest.TestCase): cue.setup_for_build(self.args) self.assertTrue(cue.has_test_results, 'Target test-results not detected') + def test_ExtraMakeArgs(self): + os.environ['EXTRA'] = 'bla' + for ind in range(1,5): + os.environ['EXTRA{0}'.format(ind)] = 'bla {0}'.format(ind) + cue.setup_for_build(self.args) + self.assertTrue(cue.extra_makeargs[0] == 'bla', 'Extra make arg [0] not set') + for ind in range(1,5): + self.assertTrue(cue.extra_makeargs[ind] == 'bla {0}'.format(ind), + 'Extra make arg [{0}] not set (expected "bla {0}", found "{1}")' + .format(ind, cue.extra_makeargs[ind])) if __name__ == "__main__": if 'VV' in os.environ and os.environ['VV'] == '1': diff --git a/cue.py b/cue.py index c3cfe33..90ef143 100644 --- a/cue.py +++ b/cue.py @@ -73,6 +73,7 @@ seen_setups = [] modules_to_compile = [] setup = {} places = {} +extra_makeargs = [] is_base314 = False is_make3 = False @@ -85,6 +86,7 @@ def clear_lists(): global is_base314, has_test_results, silent_dep_builds, is_make3 del seen_setups[:] del modules_to_compile[:] + del extra_makeargs[:] setup.clear() places.clear() is_base314 = False @@ -328,6 +330,7 @@ def call_make(args=[], **kws): place = kws.get('cwd', os.getcwd()) parallel = kws.pop('parallel', 2) silent = kws.pop('silent', False) + use_extra = kws.pop('use_extra', False) # no parallel make for Base 3.14 if parallel <= 0 or is_base314: makeargs = [] @@ -337,6 +340,8 @@ def call_make(args=[], **kws): makeargs += ['-Otarget'] if silent: makeargs += ['-s'] + if use_extra: + makeargs += extra_makeargs logger.debug("EXEC '%s' in %s", ' '.join(['make'] + makeargs + args), place) sys.stdout.flush() exitcode = sp.call(['make'] + makeargs + args, **kws) @@ -606,6 +611,11 @@ def setup_for_build(args): os.environ['PATH'] = os.pathsep.join([os.environ['PATH']] + addpaths) + # Add EXTRA make arguments + for tag in ['EXTRA', 'EXTRA1', 'EXTRA2', 'EXTRA3', 'EXTRA4', 'EXTRA5']: + if tag in os.environ: + extra_makeargs.append(os.environ[tag]) + def prepare(args): host_info() From fd4bc0397ac2b57b679f405a81edc94a18bdd67b Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 8 Jun 2020 11:04:41 +0200 Subject: [PATCH 46/55] Add EXTRA definitions to the example builds --- .appveyor.yml | 3 +++ .travis.yml | 30 ++++++++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 967752d..0fdbde4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -86,6 +86,9 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMP: vs2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + EXTRA: EXTRA_DEF="extra" + EXTRA1: EXTRA1_DEF="extra 1" + EXTRA2: EXTRA2_DEF="extra 2" - CMP: vs2015 - CMP: vs2013 - CMP: vs2012 diff --git a/.travis.yml b/.travis.yml index 43133a6..06a809a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,18 +50,20 @@ script: # Define build jobs # Well-known variables to use -# SET source setup file -# EXTRA content will be added to make command line -# STATIC set to YES for static build (default: NO) -# TEST set to NO to skip running the tests (default: YES) -# VV set to make build scripts verbose (default: unset) +# SET source setup file +# ADD_MODULES extra modules (for a specific job) +# EXTRA content will be added to make command line +# BCFG build configuration (static/debug/static-debug; +# default: shared-optimized) +# TEST set to NO to skip running the tests (default: YES) +# VV set to make build scripts verbose (default: unset) # Usually from setup files, but may be specified or overridden # on a job line -# MODULES list of dependency modules -# BASE branch or release tag name of the EPICS Base to use -# branch or release tag for a specific module -# ... see README for setup file syntax description +# MODULES list of dependency modules +# BASE branch or release tag name of the EPICS Base to use +# branch or release tag for a specific module +# ... see README for setup file syntax description jobs: include: @@ -96,7 +98,7 @@ jobs: - env: SET=test01 BCFG=static-debug dist: trusty - - env: SET=test01 + - env: SET=test01 EXTRA="CMD_CXXFLAGS=-std=c++11" - env: SET=test01 BCFG=static - env: SET=test01 BCFG=debug - env: SET=test01 BCFG=static-debug @@ -107,8 +109,12 @@ jobs: - env: SET=test01 BCFG=static-debug compiler: clang - - env: SET=test01 - os: osx + - os: osx + env: + - SET=test01 + - EXTRA=CMD_CFLAGS="-mmacosx-version-min=10.7" + - EXTRA1=CMD_CXXFLAGS="-mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++" + - EXTRA2=CMD_LDXFLAGS="-mmacosx-version-min=10.7 -std=c++11 -stdlib=libc++" compiler: clang - env: SET=test01 BCFG=debug From 4de8c6240d0fbff82328a2f02b2b8c4c96f2bcc0 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 10 Jun 2020 14:43:03 +0200 Subject: [PATCH 47/55] README: remove 'Bash on MacOS' from FAQ --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 8627062..b36f726 100644 --- a/README.md +++ b/README.md @@ -276,13 +276,6 @@ be advisable to clear the CI caches after updating ci-scripts. E.g., a change in setting up EPICS Base will not be applied if Base is found in the cache. -**Why does running the scripts locally on my MacOS machine fail?** - -The ci-scripts for Travis-CI require Bash version 4. -As Apple ships an older Bash for [political reasons][reddit.bash], -you need to install a more recent Bash, e.g. using MacPorts -or Homebrew. - ## Release Numbering of this Module The module tries to apply [Semantic Versioning](https://semver.org/). From 35f5befa9d06caea5e882410e57b9e3311aaf279 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 10 Jun 2020 14:49:26 +0200 Subject: [PATCH 48/55] cue: fix misleading error message (setup file not found) --- cue.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cue.py b/cue.py index 90ef143..3d8874d 100644 --- a/cue.py +++ b/cue.py @@ -254,9 +254,9 @@ def source_set(name): setup[assign[0]] = assign[1] logger.debug('Done with setup file %s', set_file) break - else: - raise NameError("{0}Setup file {1} does not exist in SETUP_PATH search path ({2}){3}" - .format(ANSI_RED, name, setup_dirs, ANSI_RESET)) + else: + raise NameError("{0}Setup file {1}.set does not exist in SETUP_PATH search path ({2}){3}" + .format(ANSI_RED, name, setup_dirs, ANSI_RESET)) # update_release_local(var, location) From 3dff483254d5dbe1a0c73122d5a0474c9acd85a7 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 11 Jun 2020 18:45:03 +0200 Subject: [PATCH 49/55] travis: add unit test and test build jobs for Python 3.7 --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 06a809a..aa9d2c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,6 +74,12 @@ jobs: install: python cue-test.py env script: python cue-test.py + - env: SET=test00 TRAVIS_COMPILER=gcc + language: python + python: "3.7" + install: python cue-test.py env + script: python cue-test.py + - env: SET=test00 os: osx install: python cue-test.py env @@ -98,6 +104,10 @@ jobs: - env: SET=test01 BCFG=static-debug dist: trusty + - env: SET=test01 TRAVIS_COMPILER=gcc + language: python + python: "3.7" + - env: SET=test01 EXTRA="CMD_CXXFLAGS=-std=c++11" - env: SET=test01 BCFG=static - env: SET=test01 BCFG=debug From 769a8ad08d6c9b6053f555b5e2d7670cbfb5d6d5 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 11 Jun 2020 19:33:25 +0200 Subject: [PATCH 50/55] cue: properly decode() subprocess.check_output() (breaks on Python 3) --- cue-test.py | 4 ++-- cue.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cue-test.py b/cue-test.py index 0561f25..4286a7d 100644 --- a/cue-test.py +++ b/cue-test.py @@ -232,7 +232,7 @@ class TestAddDependencyUpToDateCheck(unittest.TestCase): def is_shallow_repo(place): - check = sp.check_output(['git', 'rev-parse', '--is-shallow-repository'], cwd=place).strip() + check = sp.check_output(['git', 'rev-parse', '--is-shallow-repository'], cwd=place).strip().decode('ascii') if check == '--is-shallow-repository': if os.path.exists(os.path.join(place, '.git', 'shallow')): check = 'true' @@ -276,7 +276,7 @@ class TestAddDependencyOptions(unittest.TestCase): cue.setup['MCoreUtils_DEPTH'] = '3' cue.add_dependency('MCoreUtils') self.assertTrue(is_shallow_repo(self.location), - 'Module not checked out shallow (requested: default=5)') + 'Module not checked out shallow (requested: depth=3)') def test_AddMsiTo314(self): cue.complete_setup('BASE') diff --git a/cue.py b/cue.py index 3d8874d..d642754 100644 --- a/cue.py +++ b/cue.py @@ -514,7 +514,7 @@ def detect_epics_host_arch(): ] for eha in eha_scripts: if os.path.exists(eha): - os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]).strip() + os.environ['EPICS_HOST_ARCH'] = sp.check_output(['perl', eha]).decode('ascii').strip() logger.debug('%s returned: %s', eha, os.environ['EPICS_HOST_ARCH']) break @@ -594,7 +594,7 @@ def setup_for_build(args): has_test_results = True # Check make version - if re.match(r'^GNU Make 3', sp.check_output(['make', '-v'])): + if re.match(r'^GNU Make 3', sp.check_output(['make', '-v']).decode('ascii')): is_make3 = True # apparently %CD% is handled automagically @@ -847,7 +847,8 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS']) stat = 'rebuilt' else: stat = 'from cache' - commit = sp.check_output(['git', 'log', '-n1', '--oneline'], cwd=places[setup[mod + "_VARNAME"]]).strip() + commit = sp.check_output(['git', 'log', '-n1', '--oneline'], cwd=places[setup[mod + "_VARNAME"]])\ + .decode('ascii').strip() print("%-10s %-12s %-11s %s" % (mod, setup[mod], stat, commit)) print('{0}Contents of RELEASE.local{1}'.format(ANSI_CYAN, ANSI_RESET)) From ce4ef0b577ed56826a2c97b32840ccbbc9a0dbed Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 12 Jun 2020 20:13:42 +0200 Subject: [PATCH 51/55] Update README: document cue.py, add migration hints --- README.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b36f726..18e2bcf 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,33 @@ for more details. 5. Push your changes and check the CI service for your build results. +## Calling the cue.py Script + +Independent from CI service and platform, the runner +script is called from your main configuration as: + +`python .ci/cue.py ` + +where `` is one of: + +`prepare`\ +Prepare the build by cloning Base and the configured dependency modules, +set up the EPICS build system, then +compile Base and these modules in the order they appear in the `MODULES` +setting. + +`build`\ +Build your main module. + +`test`\ +Run the tests of your main module. + +`test-results`\ +Collect the results of your tests and print a summary. + +`exec`\ +Execute the remainder of the line using the default command shell. + ## Setup Files Your module might depend on EPICS Base and a few other support modules. @@ -132,19 +159,23 @@ combination of dependency releases, that do a few scans of the available for stable versions that many of your users have in production, one for the latest released versions and one for the development branches. +A job uses a setup file if `SET=` (without the `.set` extension +of the setup file) is set for the job in the main configuration file. + ## Setup File Syntax -Setup files are loaded by the build scripts. They are found by searching +Setup files are loaded by the build script. They are found by searching the locations in `SETUP_PATH` (space or colon separated list of directories, relative to your module's root directory). Setup files can include other setup files by calling `include ` -(omitting the `.set` extension of the setup file). The configured +(again omitting the `.set` extension of the setup file). The configured `SETUP_PATH` is searched for the include. -Any `VAR=value` setting of a variable is only executed if `VAR` is unset or -empty. That way any settings can be overridden by settings in the main -configuration (e.g., `.travis.yml`). +Any `VAR=value` setting of a variable in a setup file is only executed if +`VAR` is unset or empty. +That way any settings can be overridden by setting them in the job +description inside the main configuration file (e.g., `.travis.yml`). Empty lines or lines starting with `#` are ignored. @@ -153,8 +184,9 @@ by using their well-known slugs, separated by spaces. EPICS Base (slug: `base`) will always be a dependency and will be added and compiled first. The other dependencies are added and compiled in the order they are defined in `MODULES`. + Modules needed only for specific jobs (e.g., on specific architectures) -can be added in the main configuration file by setting `ADD_MODULES` +can be added from the main configuration file by setting `ADD_MODULES` for the specific job(s). `REPOOWNER=` sets the default GitHub owner (or organization) for all @@ -219,30 +251,75 @@ in the service specific subdirectories: - [Travis-CI README](travis/README.md) - [AppVeyor README](appveyor/README.md) - ## References: EPICS Modules Using ci-scripts [EPICS Base](https://github.com/epics-base/epics-base) and its submodules [pvData](https://github.com/epics-base/pvDataCPP), [pvAccess](https://github.com/epics-base/pvAccessCPP), -[pva2pva](https://github.com/epics-base/pva2pva) +[pva2pva](https://github.com/epics-base/pva2pva), +[PVXS](https://github.com/mdavidsaver/pvxs) EPICS Modules: [ASYN](https://github.com/epics-modules/asyn), [devlib2](https://github.com/epics-modules/devlib2), [ecmc](https://github.com/epics-modules/ecmc), +[gtest](https://github.com/epics-modules/gtest), [ip](https://github.com/epics-modules/ip), [lua](https://github.com/epics-modules/lua), [MCoreUtils](https://github.com/epics-modules/MCoreUtils), [modbus](https://github.com/epics-modules/modbus), [motor](https://github.com/epics-modules/motor), +[OPCUA](https://github.com/ralphlange/opcua), [PCAS](https://github.com/epics-modules/pcas), [sscan](https://github.com/epics-modules/sscan), [vac](https://github.com/epics-modules/vac) ESS: [EtherCAT MC Motor Driver][ref.ethercatmc] -ITER: [OPC UA Device Support](https://github.com/ralphlange/opcua) +## Migration Hints + +Look for changes in the example configuration files, and check how they +apply to your module. + +If comments in the example have changed, copy them to your configuration +to always have up-to-date documentation in your file. + +### 2.x to 3.x Migration + +Update the script and test settings in your configuration to call the +new script, following the example file. + +`python .ci/cue.py ` + +#### AppVeyor + +The `configuration:` setting options have changed; they are now +`default`, `static`, `debug` and `static-debug`. + +MinGW builds are now using the `CMP: gcc` compiler setting. + +Adding arguments to make is supported through the `EXTRA` .. `EXTRA5` +variables. Each variable value will be passed as one argument. + +#### Travis + +The new `BCFG` (build configuration) variable accepts the same options as +the AppVeyor `configuration:` setting. Replace any`STATIC=YES` settings with +`BCFG=static`. + +Remove `bash` in the `homebrew:` section of `addons:`. There are no more +bash scripts. + +MinGW builds (cross-builds using WINE as well as native builds on Windows) +are now using the `gcc` compiler setting. +Since `gcc` is the default, you can simply remove `compiler: mingw` lines. + +For Windows, Travis offers native MinGW and Visual Studio 2017 compilers. +Use `os: windows` and set `compiler:` to `gcc` or `vs2017` + for those builds. + +Chocolatey packages to be installed for the Windows jobs are set by adding +them to the environment variable `CHOCO`. ## Frequently Asked Questions @@ -251,7 +328,7 @@ ITER: [OPC UA Device Support](https://github.com/ralphlange/opcua) Set `VV=1` in the configuration line of the job you are interested in. This will make all builds (not just for your module) verbose. -**How do I update my module to use a newer release of ci-scripts?** +**How do I update my module to use a newer minor release of ci-scripts?** Update the submodule in `.ci` first, then change your CI configuration (if needed) and commit both to your module. E.g., to update your Travis @@ -276,6 +353,11 @@ be advisable to clear the CI caches after updating ci-scripts. E.g., a change in setting up EPICS Base will not be applied if Base is found in the cache. +**How do I add a dependency module only for a specific job?** + +Add the additional dependency in the main configuration file by setting +`ADD_MODULES` for the specific job(s). + ## Release Numbering of this Module The module tries to apply [Semantic Versioning](https://semver.org/). From 22652da198ed7de4aa1a66746d59a704c56f1e7c Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 15 Jun 2020 09:30:47 +0200 Subject: [PATCH 52/55] cue: support setting TEST=NO to skip tests --- cue-test.py | 16 ++++++++++++++++ cue.py | 42 +++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/cue-test.py b/cue-test.py index 4286a7d..18947b5 100644 --- a/cue-test.py +++ b/cue-test.py @@ -422,6 +422,14 @@ class TestTravisDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: static-debug)" .format(cue.ci['configuration'])) + def test_TestNo(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'linux' + os.environ['TRAVIS_COMPILER'] = 'gcc' + os.environ['TEST'] = 'NO' + cue.detect_context() + self.assertFalse(cue.ci['test'], "ci['test'] is True (expected: False)") + def test_WindowsGccNone(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' @@ -607,6 +615,14 @@ class TestAppveyorDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: static-debug)" .format(cue.ci['configuration'])) + def test_TestNo(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'gcc' + os.environ['TEST'] = 'NO' + cue.detect_context() + self.assertFalse(cue.ci['test'], "ci['test'] is True (expected: False)") + def test_WindowsGccNone(self): os.environ['APPVEYOR'] = 'True' os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' diff --git a/cue.py b/cue.py index d642754..98d28a0 100644 --- a/cue.py +++ b/cue.py @@ -62,8 +62,12 @@ def detect_context(): if 'CHOCO' in os.environ: ci['choco'].extend(os.environ['CHOCO'].split()) - logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s', - ci['service'], ci['compiler'], ci['os'], ci['platform'], ci['configuration']) + ci['test'] = True + if 'TEST' in os.environ and os.environ['TEST'].lower() == 'no': + ci['test'] = False + + logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s (test: %s)', + ci['service'], ci['compiler'], ci['os'], ci['platform'], ci['configuration'], ci['test']) curdir = os.getcwd() @@ -864,24 +868,32 @@ def build(args): def test(args): - setup_for_build(args) - fold_start('test.module', 'Run the main module tests') - if has_test_results: - call_make(['tapfiles']) + if ci['test']: + setup_for_build(args) + fold_start('test.module', 'Run the main module tests') + if has_test_results: + call_make(['tapfiles']) + else: + call_make(['runtests']) + fold_end('test.module', 'Run the main module tests') else: - call_make(['runtests']) - fold_end('test.module', 'Run the main module tests') + print("{0}Action 'test' skipped as per configuration{1}" + .format(ANSI_YELLOW, ANSI_RESET)) def test_results(args): - setup_for_build(args) - fold_start('test.results', 'Sum up main module test results') - if has_test_results: - call_make(['test-results'], parallel=0, silent=True) + if ci['test']: + setup_for_build(args) + fold_start('test.results', 'Sum up main module test results') + if has_test_results: + call_make(['test-results'], parallel=0, silent=True) + else: + print("{0}Base in {1} does not implement 'test-results' target{2}" + .format(ANSI_YELLOW, places['EPICS_BASE'], ANSI_RESET)) + fold_end('test.results', 'Sum up main module test results') else: - print("{0}Base in {1} does not implement 'test-results' target{2}" - .format(ANSI_YELLOW, places['EPICS_BASE'], ANSI_RESET)) - fold_end('test.results', 'Sum up main module test results') + print("{0}Action 'test-results' skipped as per configuration{1}" + .format(ANSI_YELLOW, ANSI_RESET)) def doExec(args): From 7585b573d35a23b215854eabf210c4220c701c10 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 15 Jun 2020 10:42:37 +0200 Subject: [PATCH 53/55] cue: warnings for STATIC and misspelled configuration fixes #47 --- cue-test.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ cue.py | 25 +++++++++++++++++-------- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/cue-test.py b/cue-test.py index 18947b5..e25b6c4 100644 --- a/cue-test.py +++ b/cue-test.py @@ -512,6 +512,28 @@ class TestTravisDetectContext(unittest.TestCase): "ci['configuration'] is {0} (expected: shared-optimized)" .format(cue.ci['configuration'])) + def test_StaticGetsWarning(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'osx' + os.environ['TRAVIS_COMPILER'] = 'clang' + os.environ['STATIC'] = 'YES' + capturedOutput = getStringIO() + sys.stdout = capturedOutput + cue.detect_context() + sys.stdout = sys.__stdout__ + self.assertRegexpMatches(capturedOutput.getvalue(), "Variable 'STATIC' not supported anymore") + + def test_MisspelledBcfgGetsWarning(self): + os.environ['TRAVIS'] = 'true' + os.environ['TRAVIS_OS_NAME'] = 'osx' + os.environ['TRAVIS_COMPILER'] = 'clang' + os.environ['BCFG'] = 'static-dubug' + capturedOutput = getStringIO() + sys.stdout = capturedOutput + cue.detect_context() + sys.stdout = sys.__stdout__ + self.assertRegexpMatches(capturedOutput.getvalue(), "Unrecognized build configuration setting") + @unittest.skipIf(ci_service != 'appveyor', 'Run appveyor tests only on appveyor') class TestAppveyorDetectContext(unittest.TestCase): @@ -689,6 +711,28 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") + def test_StaticGetsWarning(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['STATIC'] = 'YES' + capturedOutput = getStringIO() + sys.stdout = capturedOutput + cue.detect_context() + sys.stdout = sys.__stdout__ + self.assertRegexpMatches(capturedOutput.getvalue(), "Variable 'STATIC' not supported anymore") + + def test_MisspelledConfigurationGetsWarning(self): + os.environ['APPVEYOR'] = 'True' + os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' + os.environ['CMP'] = 'vs2019' + os.environ['CONFIGURATION'] = 'static-dubug' + capturedOutput = getStringIO() + sys.stdout = capturedOutput + cue.detect_context() + sys.stdout = sys.__stdout__ + self.assertRegexpMatches(capturedOutput.getvalue(), "Unrecognized build configuration setting") + class TestSetupForBuild(unittest.TestCase): args = Namespace(paths=[]) diff --git a/cue.py b/cue.py index 98d28a0..a9c2477 100644 --- a/cue.py +++ b/cue.py @@ -16,6 +16,7 @@ logger = logging.getLogger(__name__) # Detect the service and set up context hash accordingly def detect_context(): + buildconfig = 'default' if 'TRAVIS' in os.environ: ci['service'] = 'travis' ci['os'] = os.environ['TRAVIS_OS_NAME'] @@ -27,10 +28,7 @@ def detect_context(): # Only Visual Studio 2017 available ci['compiler'] = 'vs2017' if 'BCFG' in os.environ: - if re.search('static', os.environ['BCFG']): - ci['static'] = True - if re.search('debug', os.environ['BCFG']): - ci['debug'] = True + buildconfig = os.environ['BCFG'].lower() if 'APPVEYOR' in os.environ: ci['service'] = 'appveyor' @@ -43,10 +41,21 @@ def detect_context(): ci['platform'] = os.environ['PLATFORM'].lower() if 'CMP' in os.environ: ci['compiler'] = os.environ['CMP'] - if re.search('static', os.environ['CONFIGURATION']): - ci['static'] = True - if re.search('debug', os.environ['CONFIGURATION']): - ci['debug'] = True + buildconfig = os.environ['CONFIGURATION'].lower() + + if 'STATIC' in os.environ: + print("{0}WARNING: Variable 'STATIC' not supported anymore; use 'BCFG' instead{1}" + .format(ANSI_RED, ANSI_RESET)) + sys.stdout.flush() + if not re.match(r'^((default|static|shared|dynamic|optimized|debug)-?)+$', buildconfig): + print("{0}WARNING: Unrecognized build configuration setting '{1}'{2}" + .format(ANSI_RED, buildconfig, ANSI_RESET)) + sys.stdout.flush() + + if re.search('static', buildconfig): + ci['static'] = True + if re.search('debug', buildconfig): + ci['debug'] = True if ci['static']: ci['configuration'] = 'static' From 3931ff04fc7c75ceb6d4890f936b906c5a4cfcad Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 15 Jun 2020 10:35:55 +0200 Subject: [PATCH 54/55] cue-test: clean up DetectContext tests --- cue-test.py | 98 ++++++++++------------------------------------------- 1 file changed, 18 insertions(+), 80 deletions(-) diff --git a/cue-test.py b/cue-test.py index e25b6c4..4f7124d 100644 --- a/cue-test.py +++ b/cue-test.py @@ -332,14 +332,18 @@ class TestVCVars(unittest.TestCase): @unittest.skipIf(ci_service != 'travis', 'Run travis tests only on travis') class TestTravisDetectContext(unittest.TestCase): - def tearDown(self): - cue.clear_lists() - os.environ.pop('BCFG', None) - - def test_LinuxGccNone(self): + def setUp(self): os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'gcc' + + def tearDown(self): + cue.clear_lists() + os.environ.pop('BCFG', None) + os.environ.pop('TEST', None) + os.environ.pop('STATIC', None) + + def test_LinuxGccNone(self): cue.detect_context() self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" .format(cue.ci['service'])) @@ -356,8 +360,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_LinuxClangNone(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' os.environ['TRAVIS_COMPILER'] = 'clang' cue.detect_context() self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" @@ -375,9 +377,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_BcfgShared(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' - os.environ['TRAVIS_COMPILER'] = 'gcc' os.environ['BCFG'] = 'shared' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") @@ -387,9 +386,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_BcfgStatic(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' - os.environ['TRAVIS_COMPILER'] = 'gcc' os.environ['BCFG'] = 'static' cue.detect_context() self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") @@ -399,9 +395,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_BcfgDebug(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' - os.environ['TRAVIS_COMPILER'] = 'gcc' os.environ['BCFG'] = 'debug' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") @@ -411,9 +404,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_BcfgStaticDebug(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' - os.environ['TRAVIS_COMPILER'] = 'gcc' os.environ['BCFG'] = 'static-debug' cue.detect_context() self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") @@ -423,17 +413,12 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_TestNo(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'linux' - os.environ['TRAVIS_COMPILER'] = 'gcc' os.environ['TEST'] = 'NO' cue.detect_context() self.assertFalse(cue.ci['test'], "ci['test'] is True (expected: False)") def test_WindowsGccNone(self): - os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' - os.environ['TRAVIS_COMPILER'] = 'gcc' cue.detect_context() self.assertEqual(cue.ci['service'], 'travis', "ci['service'] is {0} (expected: travis)" .format(cue.ci['service'])) @@ -452,7 +437,6 @@ class TestTravisDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_WindowsVs2017None(self): - os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' os.environ['TRAVIS_COMPILER'] = 'vs2017' cue.detect_context() @@ -473,7 +457,6 @@ class TestTravisDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_WindowsVs2019None(self): - os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'windows' os.environ['TRAVIS_COMPILER'] = 'vs2019' cue.detect_context() @@ -494,7 +477,6 @@ class TestTravisDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_OsxClangNone(self): - os.environ['TRAVIS'] = 'true' os.environ['TRAVIS_OS_NAME'] = 'osx' os.environ['TRAVIS_COMPILER'] = 'clang' cue.detect_context() @@ -513,9 +495,6 @@ class TestTravisDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_StaticGetsWarning(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'osx' - os.environ['TRAVIS_COMPILER'] = 'clang' os.environ['STATIC'] = 'YES' capturedOutput = getStringIO() sys.stdout = capturedOutput @@ -524,9 +503,6 @@ class TestTravisDetectContext(unittest.TestCase): self.assertRegexpMatches(capturedOutput.getvalue(), "Variable 'STATIC' not supported anymore") def test_MisspelledBcfgGetsWarning(self): - os.environ['TRAVIS'] = 'true' - os.environ['TRAVIS_OS_NAME'] = 'osx' - os.environ['TRAVIS_COMPILER'] = 'clang' os.environ['BCFG'] = 'static-dubug' capturedOutput = getStringIO() sys.stdout = capturedOutput @@ -537,15 +513,19 @@ class TestTravisDetectContext(unittest.TestCase): @unittest.skipIf(ci_service != 'appveyor', 'Run appveyor tests only on appveyor') class TestAppveyorDetectContext(unittest.TestCase): - def tearDown(self): - cue.clear_lists() - os.environ.pop('CONFIGURATION', None) - - def test_Platform32(self): + def setUp(self): os.environ['APPVEYOR'] = 'True' os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' os.environ['CMP'] = 'vs2019' os.environ['CONFIGURATION'] = 'default' + os.environ['PLATFORM'] = 'x64' + + def tearDown(self): + cue.clear_lists() + os.environ.pop('STATIC', None) + os.environ.pop('TEST', None) + + def test_Platform32(self): os.environ['PLATFORM'] = 'x86' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") @@ -558,11 +538,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['platform'])) def test_Platform64(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'vs2019' - os.environ['CONFIGURATION'] = 'default' - os.environ['PLATFORM'] = 'x64' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") @@ -574,10 +549,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['platform'])) def test_PlatformX64(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'vs2019' - os.environ['CONFIGURATION'] = 'default' os.environ['PLATFORM'] = 'X64' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") @@ -590,10 +561,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['platform'])) def test_ConfigDefault(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'gcc' - os.environ['CONFIGURATION'] = 'default' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") self.assertFalse(cue.ci['debug'], "ci['debug'] is True (expected: False)") @@ -602,9 +569,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_ConfigStatic(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'gcc' os.environ['CONFIGURATION'] = 'static' cue.detect_context() self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") @@ -614,9 +578,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_ConfigDebug(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'gcc' os.environ['CONFIGURATION'] = 'debug' cue.detect_context() self.assertFalse(cue.ci['static'], "ci['static'] is True (expected: False)") @@ -626,9 +587,6 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_ConfigStaticDebug(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'gcc' os.environ['CONFIGURATION'] = 'static-debug' cue.detect_context() self.assertTrue(cue.ci['static'], "ci['static'] is False (expected: True)") @@ -638,19 +596,12 @@ class TestAppveyorDetectContext(unittest.TestCase): .format(cue.ci['configuration'])) def test_TestNo(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'gcc' os.environ['TEST'] = 'NO' cue.detect_context() self.assertFalse(cue.ci['test'], "ci['test'] is True (expected: False)") def test_WindowsGccNone(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' os.environ['CMP'] = 'gcc' - os.environ['CONFIGURATION'] = 'default' - os.environ['PLATFORM'] = 'x64' cue.detect_context() self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" .format(cue.ci['service'])) @@ -668,10 +619,8 @@ class TestAppveyorDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_WindowsVs2017None(self): - os.environ['APPVEYOR'] = 'True' os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2017' os.environ['CMP'] = 'vs2017' - os.environ['CONFIGURATION'] = 'default' os.environ['PLATFORM'] = 'x86' cue.detect_context() self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" @@ -690,11 +639,6 @@ class TestAppveyorDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_WindowsVs2019None(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'vs2019' - os.environ['CONFIGURATION'] = 'default' - os.environ['PLATFORM'] = 'x64' cue.detect_context() self.assertEqual(cue.ci['service'], 'appveyor', "ci['service'] is {0} (expected: appveyor)" .format(cue.ci['service'])) @@ -712,9 +656,6 @@ class TestAppveyorDetectContext(unittest.TestCase): self.assertIn('make', cue.ci['choco'], "'make' is not in ci['choco']") def test_StaticGetsWarning(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'vs2019' os.environ['STATIC'] = 'YES' capturedOutput = getStringIO() sys.stdout = capturedOutput @@ -723,9 +664,6 @@ class TestAppveyorDetectContext(unittest.TestCase): self.assertRegexpMatches(capturedOutput.getvalue(), "Variable 'STATIC' not supported anymore") def test_MisspelledConfigurationGetsWarning(self): - os.environ['APPVEYOR'] = 'True' - os.environ['APPVEYOR_BUILD_WORKER_IMAGE'] = 'Visual Studio 2019' - os.environ['CMP'] = 'vs2019' os.environ['CONFIGURATION'] = 'static-dubug' capturedOutput = getStringIO() sys.stdout = capturedOutput From 9c89437dacfab4f85c29f7e01210c9ae87a0629f Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Mon, 15 Jun 2020 11:07:50 +0200 Subject: [PATCH 55/55] cue: support PARALLEL_MAKE to configure number of make jobs fixes #46 --- README.md | 5 ++++- cue.py | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 18e2bcf..ba68d7d 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,10 @@ builds to higher verbosity. For debugging on your local machine, you may set `CACHEDIR` to change the location for the dependency builds. [default is `$HOME/.cache`] -Service specific debugging options are described in the README files +Set `PARALLEL_MAKE` to the number of parallel make jobs that you want your +build to use. [default is the number of CPUs on the runner] + +Service specific options are described in the README files in the service specific subdirectories: - [Travis-CI README](travis/README.md) diff --git a/cue.py b/cue.py index a9c2477..34d59ad 100644 --- a/cue.py +++ b/cue.py @@ -75,6 +75,10 @@ def detect_context(): if 'TEST' in os.environ and os.environ['TEST'].lower() == 'no': ci['test'] = False + ci['parallel_make'] = 2 + if 'PARALLEL_MAKE' in os.environ: + ci['parallel_make'] = os.environ['PARALLEL_MAKE'] + logger.debug('Detected a build hosted on %s, using %s on %s (%s) configured as %s (test: %s)', ci['service'], ci['compiler'], ci['os'], ci['platform'], ci['configuration'], ci['test']) @@ -341,7 +345,7 @@ def call_git(args, **kws): def call_make(args=[], **kws): place = kws.get('cwd', os.getcwd()) - parallel = kws.pop('parallel', 2) + parallel = kws.pop('parallel', ci['parallel_make']) silent = kws.pop('silent', False) use_extra = kws.pop('use_extra', False) # no parallel make for Base 3.14