diff --git a/.appveyor.yml b/.appveyor.yml
index e6b034c..c52387c 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -37,6 +37,7 @@ skip_commits:
- '**/*.html'
- '**/*.md'
- '.travis.yml'
+ - '.github/workflows/*'
#---------------------------------#
# additional packages #
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000..1411fc9
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,156 @@
+name: ci-scripts build/test
+
+on:
+ push:
+ branches: [ devel/gh-actions ]
+
+env:
+ SETUP_PATH: .:.ci
+ SET: test01
+ VV: 1
+ BASE_RECURSIVE: NO
+ CMP: gcc
+ APT: re2c
+ CHOCO: re2c
+ BREW: re2c
+
+jobs:
+ unit-test:
+ name: Unit tests on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, windows-2019, windows-2016, macos-10.15]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Show initial environment
+ run: python cue-test.py env
+ - name: Run unit tests
+ run: python cue-test.py
+
+ build-linux:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
+ cmp: [gcc, clang]
+ configuration: [default, static, debug, static-debug]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module (example app)
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-macos:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [macos-10.15]
+ cmp: [clang]
+ configuration: [default, debug]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module (example app)
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-windows:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-2019, windows-2016]
+ cmp: [gcc, vs2019, vs2017]
+ configuration: [default, static, debug, static-debug]
+ exclude:
+ - os: windows-2019
+ cmp: vs2017
+ - os: windows-2016
+ cmp: vs2019
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module (example app)
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-rtems:
+ name: RTEMS${{ matrix.rtems }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ RTEMS: ${{ matrix.rtems }}
+ APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64 qemu-system-x86
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-18.04]
+ cmp: [gcc]
+ configuration: [default, static, debug, static-debug]
+ rtems: ["4.9", "4.10"]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module (example app)
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-wine:
+ name: WINE${{ matrix.wine }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ WINE: ${{ matrix.wine }}
+ APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-18.04]
+ cmp: [gcc]
+ configuration: [default, static, debug, static-debug]
+ wine: [32, 64]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module (example app)
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
diff --git a/README.md b/README.md
index 48a1db1..ea9a237 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
![Version][badge.version]
![Travis status][badge.travis]
![AppVeyor status][badge.appveyor]
+![GitHub Actions status][badge.gh-actions]
# Continuous Integration for EPICS Modules
@@ -58,12 +59,12 @@ levels as the example files.
### [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.15)
+ - Ubuntu 12/14/16/18, MacOS 10.13, Windows Server v1809
+ - Compile natively on Linux (different versions of gcc, clang)
- Compile natively on MacOS (clang)
- Compile natively on Windows (gcc/MinGW, Visual Studio 2017)
+ - Cross-compile for Windows 32bit and 64bit using MinGW and WINE
+ - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
- Built dependencies are cached (for faster builds).
See specific
@@ -72,8 +73,8 @@ for more details.
### [AppVeyor](https://www.appveyor.com/)
- One parallel runner (all builds are sequential)
- - Use different compilers (Visual Studio, gcc/MinGW)
- - Use different Visual Studio versions: \
+ - Windows Server 2012/2016/2019
+ - Compile using gcc/MinGW or different Visual Studio versions: \
2008, 2010, 2012, 2013, 2015, 2017, 2019
- Compile for Windows 32bit and 64bit
- No useful caching available.
@@ -82,15 +83,30 @@ See specific
**[ci-scripts on AppVeyor README](appveyor/README.md)**
for more details.
+### [GitHub Actions](https://github.com/)
+ - 20 parallel runners on Linux/Windows (5 runners on MacOS)
+ - Ubuntu 16/18/20, MacOS 10.15, Windows Server 2016/2019
+ - Compile natively on Linux (gcc, clang)
+ - Compile natively on MacOS (clang)
+ - Compile natively on Windows (gcc/MinGW, Visual Studio 2017 & 2019)
+ - Cross-compile for Windows 32bit and 64bit using MinGW and WINE
+ - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
+ - Caching not supported by ci-scripts yet.
+
+See specific
+**[ci-scripts on GitHub Actions README](gh-actions/README.md)**
+for more details.
+
## How to Use the CI-Scripts
- 1. Get an account on a supported CI service provider platform.
+ 1. Get an account on a supported CI service provider platform
(e.g. [Travis-CI](https://travis-ci.org/),
- [AppVeyor](https://www.appveyor.com/), ...)
+ [AppVeyor](https://www.appveyor.com/), ...).
+ GitHub Actions does not require a separate account.
(More details in the specific README of the subdirectory.)
- 2. In your Support Module, add this ci-scripts repository
+ 2. In your module, add this ci-scripts repository
as a Git Submodule (name suggestion: `.ci`).
```bash
git submodule add https://github.com/epics-base/ci-scripts .ci
@@ -405,6 +421,7 @@ in file LICENSE that is included with this distribution.
[badge.version]: https://badge.fury.io/gh/epics-base%2Fci-scripts.svg
[badge.travis]: https://travis-ci.org/epics-base/ci-scripts.svg?branch=master
[badge.appveyor]: https://ci.appveyor.com/api/projects/status/8b578alg974axvux?svg=true
+[badge.gh-actions]: https://github.com/epics-base/ci-scripts/workflows/ci-scripts%20build/test/badge.svg
[reddit.bash]: https://www.reddit.com/r/bash/comments/393oqv/why_is_the_version_of_bash_included_in_os_x_so_old/
diff --git a/appveyor/README.md b/appveyor/README.md
index e4005f3..1e0d40d 100644
--- a/appveyor/README.md
+++ b/appveyor/README.md
@@ -3,8 +3,8 @@
## Features
- One parallel runner (all builds are sequential)
- - Use different compilers (Visual Studio, gcc/MinGW)
- - Use different Visual Studio versions: \
+ - Windows Server 2012/2016/2019
+ - Compile using gcc/MinGW or different Visual Studio versions: \
2008, 2010, 2012, 2013, 2015, 2017, 2019
- Compile for Windows 32bit and 64bit
- No useful caching available.
diff --git a/cue-test.py b/cue-test.py
index 4f7124d..b431e81 100644
--- a/cue-test.py
+++ b/cue-test.py
@@ -31,6 +31,13 @@ if 'APPVEYOR' in os.environ:
elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']):
ci_os = 'osx'
+if 'GITHUB_ACTIONS' in os.environ:
+ ci_service = 'github-actions'
+ if os.environ['RUNNER_OS'] == 'macOS':
+ ci_os = 'osx'
+ else:
+ ci_os = os.environ['RUNNER_OS'].lower()
+
def find_in_file(regex, filename):
file = open(filename, "r")
@@ -324,8 +331,14 @@ class TestDefaultModuleURLs(unittest.TestCase):
@unittest.skipIf(ci_os != 'windows', 'VCVars test only applies to windows')
class TestVCVars(unittest.TestCase):
def test_vcvars(self):
- if ci_service == 'appveyor':
+ if ci_service == 'travis':
+ os.environ['TRAVIS_COMPILER'] = 'vs2017'
+ else:
os.environ['CONFIGURATION'] = 'default'
+ if ci_service == 'github-actions' and os.environ['IMAGEOS'] == 'win16':
+ os.environ['CMP'] = 'vs2017'
+ else:
+ os.environ['CMP'] = 'vs2019'
cue.detect_context()
cue.with_vcvars('env')
@@ -676,7 +689,7 @@ class TestSetupForBuild(unittest.TestCase):
args = Namespace(paths=[])
cue.building_base = True
if ci_os == 'windows':
- sp.check_call(['choco', 'install', 'make'])
+ sp.check_call(['choco', 'install', 'make', 'strawberryperl', '-ry'])
def setUp(self):
if ci_service == 'appveyor':
@@ -726,10 +739,10 @@ class TestSetupForBuild(unittest.TestCase):
@unittest.skipIf(ci_os != 'windows', 'HostArchPlatform test only applies to windows')
def test_HostArchPlatform(self):
- if ci_service == 'travis':
- platforms = ['x64']
- else:
+ if ci_service == 'appveyor':
platforms = ['x86', 'x64']
+ else:
+ platforms = ['x64']
for platform in platforms:
for cc in ['vs2019', 'gcc']:
cue.ci['platform'] = platform
@@ -750,18 +763,17 @@ class TestSetupForBuild(unittest.TestCase):
self.assertTrue(re.search('-mingw$', os.environ['EPICS_HOST_ARCH']),
'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']))
+ if ci_service == 'appveyor':
+ pattern = {'x86': 'mingw32', 'x64': 'mingw64'}
+ self.assertTrue(re.search(pattern[platform], os.environ['PATH']),
+ 'Binary location for {0} not in PATH (found PATH = {1})'
+ .format(pattern[platform], os.environ['PATH']))
@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'
+ def test_StrawberryInPath(self):
cue.setup_for_build(self.args)
self.assertTrue(re.search('strawberry', os.environ['PATH'], flags=re.IGNORECASE),
- 'Strawberry Perl installed but location not in PATH (found {0})'
+ 'Strawberry Perl location not in PATH (found PATH = {0})'
.format(os.environ['PATH']))
def setBase314(self, yesno):
@@ -827,5 +839,14 @@ if __name__ == "__main__":
if sys.argv[1:] == ['env']:
# testing with_vcvars
[print(K, '=', V) for K, V in os.environ.items()]
+ elif ci_os == 'windows' and sys.argv[1:] == ['findvs']:
+ from fnmatch import fnmatch
+ print('Available Visual Studio versions')
+ for base in (r'C:\Program Files (x86)', r'C:\Program Files'):
+ for root, dirs, files in os.walk(base):
+ for fname in files:
+ if fnmatch(fname, 'vcvarsall.bat'):
+ print('Found', os.path.join(root, fname))
+ sys.stdout.flush()
else:
unittest.main()
diff --git a/cue.py b/cue.py
index c7732f3..6a9b737 100644
--- a/cue.py
+++ b/cue.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-"""CI build script for Linux/MacOS/Windows on Travis/AppVeyor
+"""CI build script for Linux/MacOS/Windows on Travis/AppVeyor/GitHub-Actions
"""
from __future__ import print_function
@@ -22,11 +22,10 @@ def detect_context():
ci['os'] = os.environ['TRAVIS_OS_NAME']
ci['platform'] = 'x64'
ci['compiler'] = os.environ['TRAVIS_COMPILER']
- if ci['os'] == 'windows':
- ci['choco'] += ['strawberryperl']
- if re.match(r'^vs', ci['compiler']):
- # Only Visual Studio 2017 available
- ci['compiler'] = 'vs2017'
+ ci['choco'] += ['strawberryperl']
+ if re.match(r'^vs', ci['compiler']):
+ # Only Visual Studio 2017 available
+ ci['compiler'] = 'vs2017'
if 'BCFG' in os.environ:
buildconfig = os.environ['BCFG'].lower()
@@ -43,6 +42,24 @@ def detect_context():
ci['compiler'] = os.environ['CMP']
buildconfig = os.environ['CONFIGURATION'].lower()
+ if 'GITHUB_ACTIONS' in os.environ:
+ ci['service'] = 'github-actions'
+ if os.environ['RUNNER_OS'] == 'macOS':
+ ci['os'] = 'osx'
+ else:
+ ci['os'] = os.environ['RUNNER_OS'].lower()
+ ci['platform'] = 'x64'
+ if 'CMP' in os.environ:
+ ci['compiler'] = os.environ['CMP']
+ ci['choco'] += ['strawberryperl']
+ if 'BCFG' in os.environ:
+ buildconfig = os.environ['BCFG'].lower()
+
+ if re.search('static', buildconfig):
+ ci['static'] = True
+ if re.search('debug', buildconfig):
+ ci['debug'] = True
+
if 'STATIC' in os.environ:
print("{0}WARNING: Variable 'STATIC' not supported anymore; use 'BCFG' instead{1}"
.format(ANSI_RED, ANSI_RESET))
@@ -52,11 +69,6 @@ def detect_context():
.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'
else:
@@ -74,6 +86,9 @@ def detect_context():
if 'APT' in os.environ:
ci['apt'].extend(os.environ['APT'].split())
+ if 'BREW' in os.environ:
+ ci['homebrew'].extend(os.environ['BREW'].split())
+
ci['test'] = True
if 'TEST' in os.environ and os.environ['TEST'].lower() == 'no':
ci['test'] = False
@@ -130,6 +145,7 @@ def clear_lists():
ci['scriptsdir'] = ''
ci['choco'] = ['make']
ci['apt'] = []
+ ci['homebrew'] = []
clear_lists()
@@ -153,11 +169,16 @@ ANSI_CLEAR = "\033[0K"
# Travis log fold control
# from https://github.com/travis-ci/travis-rubies/blob/build/build.sh
+# GitHub Actions fold control
+# from https://github.com/actions/toolkit/blob/master/docs/commands.md#group-and-ungroup-log-lines
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'] == 'github-actions':
+ print('::group::{0}{1}{2}'
+ .format(ANSI_YELLOW, title, ANSI_RESET))
elif ci['service'] == 'appveyor':
print('{0}===== \\/ \\/ \\/ ===== START: {1} ====={2}'
.format(ANSI_YELLOW, title, ANSI_RESET))
@@ -168,6 +189,9 @@ def fold_end(tag, title):
if ci['service'] == 'travis':
print('\ntravis_fold:end:{0}\r'
.format(tag), end='')
+ elif ci['service'] == 'github-actions':
+ print('::endgroup::'
+ .format(ANSI_YELLOW, title, ANSI_RESET))
elif ci['service'] == 'appveyor':
print('{0}----- /\\ /\\ /\\ ----- END: {1} -----{2}'
.format(ANSI_YELLOW, title, ANSI_RESET))
@@ -181,7 +205,7 @@ elif 'HOME' in os.environ:
homedir = os.getenv('HOME')
cachedir = os.path.join(homedir, '.cache')
toolsdir = os.path.join(homedir, '.tools')
-rtemsdir = os.path.join(homedir, '.rtems')
+rtemsdir = r'/home/travis/.rtems' # Preliminary, until the next generation of toolchain
if 'CACHEDIR' in os.environ:
cachedir = os.environ['CACHEDIR']
@@ -189,8 +213,10 @@ 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'],
+ 'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat',
+ r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\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\Enterprise\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'],
@@ -551,32 +577,34 @@ def setup_for_build(args):
global is_base314, has_test_results, is_make3
dllpaths = []
+ logger.debug('Setting up the build environment')
+
if ci['os'] == 'windows':
- 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['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['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',
+ if os.path.exists(r'C:\Strawberry\perl\bin'):
+ # Put strawberry perl in front of the PATH (so that Git Perl is further behind)
+ logger.debug('Adding Strawberry Perl in front of the PATH')
+ os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\c\bin',
+ r'C:\Strawberry\perl\site\bin',
+ r'C:\Strawberry\perl\bin',
os.environ['PATH']])
+ if ci['service'] == 'appveyor' and ci['compiler'] == 'gcc':
+ logger.debug('Adding AppVeyor MSYS2/MinGW installation to PATH and INCLUDE')
+ 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['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['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin',
+ os.environ['PATH']])
+
# Find BASE location
if not building_base:
with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f:
@@ -588,6 +616,8 @@ def setup_for_build(args):
else:
places['EPICS_BASE'] = '.'
+ logger.debug('Using EPICS Base at %s', places['EPICS_BASE'])
+
detect_epics_host_arch()
if ci['os'] == 'windows':
@@ -611,6 +641,7 @@ def setup_for_build(args):
with open(cfg_base_version) as myfile:
if 'BASE_3_14=YES' in myfile.read():
is_base314 = True
+ logger.debug('Check if EPICS Base is a 3.14 series: %s', is_base314)
if not is_base314:
rules_build = os.path.join(places['EPICS_BASE'], 'configure', 'RULES_BUILD')
@@ -623,6 +654,7 @@ def setup_for_build(args):
# Check make version
if re.match(r'^GNU Make 3', sp.check_output(['make', '-v']).decode('ascii')):
is_make3 = True
+ logger.debug('Check if make is a 3.x series: %s', is_make3)
# apparently %CD% is handled automagically
os.environ['TOP'] = os.getcwd()
@@ -781,14 +813,17 @@ CROSS_COMPILER_TARGET_ARCHS += windows-x64-mingw''')
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',
+ # Patch Base 3.15 that doesn't have -qemu target architecture
+ if not os.path.exists(os.path.join(places['EPICS_BASE'], 'configure', 'os',
'CONFIG.Common.RTEMS-pc386-qemu')):
- qemu_suffix = '-qemu'
+ print('Adding RTEMS-pc386-qemu target to Base in {0}'.format(places['EPICS_BASE']))
+ sys.stdout.flush()
+ sp.check_call(['patch', '-p1', '-i',
+ os.path.join(ci['scriptsdir'], 'add-RTEMS-pc368-qemu-target.patch')],
+ cwd=places['EPICS_BASE'])
with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f:
f.write('''
-CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386{0}'''.format(qemu_suffix))
+CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu''')
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'])
@@ -819,20 +854,24 @@ 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 = ''
+ # Add additional settings to CONFIG_SITE
+ extra_config = ''
if 'USR_CPPFLAGS' in os.environ:
- flags_text += '''
+ extra_config += '''
USR_CPPFLAGS += {0}'''.format(os.environ['USR_CPPFLAGS'])
if 'USR_CFLAGS' in os.environ:
- flags_text += '''
+ extra_config += '''
USR_CFLAGS += {0}'''.format(os.environ['USR_CFLAGS'])
if 'USR_CXXFLAGS' in os.environ:
- flags_text += '''
+ extra_config += '''
USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
- if flags_text:
+ if ci['service'] == 'github-actions' and ci['os'] == 'windows':
+ extra_config += '''
+PERL = C:/Strawberry/perl/bin/perl -CSD'''
+
+ if extra_config:
with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f:
- f.write(flags_text)
+ f.write(extra_config)
fold_end('set.up.epics_build', 'Configuring EPICS build system')
@@ -841,7 +880,7 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
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'] + ['-y', '--limitoutput', '--no-progress'])
fold_end('install.choco', 'Installing CHOCO packages')
if ci['os'] == 'linux' and ci['apt']:
@@ -849,6 +888,11 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
sp.check_call(['sudo', 'apt-get', '-y', 'install'] + ci['apt'])
fold_end('install.apt', 'Installing APT packages')
+ if ci['os'] == 'osx' and ci['homebrew']:
+ fold_start('install.homebrew', 'Installing Homebrew packages')
+ sp.check_call(['brew', 'install'] + ci['homebrew'])
+ fold_end('install.homebrew', 'Installing Homebrew 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}'
@@ -858,7 +902,10 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
'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)])
+ sudo_prefix = []
+ if ci['service'] == 'github-actions':
+ sudo_prefix = ['sudo']
+ sp.check_call(sudo_prefix + ['tar', '-C', '/', '-xmj', '-f', os.path.join(toolsdir, tar_name)])
os.remove(os.path.join(toolsdir, tar_name))
setup_for_build(args)
diff --git a/github-actions/README.md b/github-actions/README.md
new file mode 100644
index 0000000..77ab32d
--- /dev/null
+++ b/github-actions/README.md
@@ -0,0 +1,57 @@
+# GitHub Actions Scripts for EPICS Modules
+
+## Features
+
+ - 20 parallel runners on Linux/Windows (5 runners on MacOS)
+ - Ubuntu 16/18/20, MacOS 10.15, Windows Server 2016/2019
+ - Compile natively on Linux (gcc, clang)
+ - Compile natively on MacOS (clang)
+ - Compile natively on Windows (gcc/MinGW, Visual Studio 2017 & 2019)
+ - Cross-compile for Windows 32bit and 64bit using MinGW and WINE
+ - Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
+ - Caching not supported yet.
+
+## How to Use these Scripts
+
+ 1. Add the ci-scripts respository as a Git Submodule
+ (see [README](../README.md) one level above).
+
+ 2. Add settings files defining which dependencies in which versions
+ you want to build against
+ (see [README](../README.md) one level above).
+
+ 3. Create a GitHub Actions configuration by copying one of the workflow
+ examples into the directory `.github/workflows` of your module.
+ ```bash
+ $ mkdir -p .github/workflows
+ $ cp .ci/github-actions/ci-scripts-build.yml.example-full .github/workflows/ci-scripts-build.yml
+ ```
+
+ 4. Edit the workflow configuration to include the build jobs you want
+ GitHub Actions to run.
+
+ Build jobs are specified in the `jobs: : strategy:`
+ declaration. The `matrix:` element specifies the axes as configuration
+ parameters with their lists of values,
+ `env:` (on the build level) controls the setting of environment variables
+ (which can be matrix parameters).
+ The `runs-on:` setting specifies the image (operating system) of the
+ runner.
+ The `name:` is what shows up in the web interface for the workflow,
+ builds and jobs, and the elements under `steps:` describe the actions
+ executed for each job of the matrix.
+
+ Please check the comments in the examples for more hints, and the
+ [GitHub Actions documentation](https://help.github.com/en/actions)
+ for a lot more options and details.
+
+ 5. Push your changes and click on the `Actions` tab of your GitHub repository
+ page to see your build results.
+
+## Caches
+
+GitHub Actions provides caching of dependencies.
+
+However, since their cache restore and create algorithm is fundamentally
+different from those used by Travis and AppVeyor, this will require some
+more changes in ci-scripts to work. Be patient.
diff --git a/github-actions/ci-scripts-build.yml.example-full b/github-actions/ci-scripts-build.yml.example-full
new file mode 100644
index 0000000..412a6b6
--- /dev/null
+++ b/github-actions/ci-scripts-build.yml.example-full
@@ -0,0 +1,155 @@
+# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
+# (see: https://github.com/epics-base/ci-scripts)
+
+# This is YAML - indentation levels are crucial
+
+# Set the 'name:' properties to values that work for you (MYMODULE)
+
+name: MYMODULE ci-scripts build
+
+# Trigger on pushes and PRs to any branch
+on: [push, pull_request]
+
+env:
+ SETUP_PATH: .ci-local:.ci
+ SET: test01
+ CMP: gcc
+ # For the sequencer on Linux/Windows/MacOS
+ APT: re2c
+ CHOCO: re2c
+ BREW: re2c
+
+jobs:
+ build-linux:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ # Set environment variables from matrix parameters
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
+ cmp: [gcc, clang]
+ configuration: [default, static, debug, static-debug]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-macos:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ # Set environment variables from matrix parameters
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [macos-10.15]
+ cmp: [clang]
+ # No static builds on MacOS
+ configuration: [default, debug]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ build-windows:
+ name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-2019, windows-2016]
+ cmp: [gcc, vs2019, vs2017]
+ configuration: [default, static, debug, static-debug]
+ # Available: vs2017/windows-2016 and vs2019/windows-2019
+ exclude:
+ - os: windows-2019
+ cmp: vs2017
+ - os: windows-2016
+ cmp: vs2019
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ # Same setup and toolchain as on Travis.
+ # Needs Base >= 3.15 to compile, EPICS 7 to also run the tests on qemu
+ build-rtems:
+ name: RTEMS${{ matrix.rtems }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ RTEMS: ${{ matrix.rtems }}
+ APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64 qemu-system-x86
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-18.04]
+ cmp: [gcc]
+ configuration: [default, static, debug, static-debug]
+ rtems: ["4.9", "4.10"]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
+
+ # The WINE cross builds are of somewhat limited use,
+ # as there are native gcc/MinGW builds available on GitHub Actions
+ build-wine:
+ name: WINE${{ matrix.wine }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ WINE: ${{ matrix.wine }}
+ APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-18.04]
+ cmp: [gcc]
+ configuration: [default, static, debug, static-debug]
+ wine: [32, 64]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results
diff --git a/github-actions/ci-scripts-build.yml.example-mini b/github-actions/ci-scripts-build.yml.example-mini
new file mode 100644
index 0000000..6c20072
--- /dev/null
+++ b/github-actions/ci-scripts-build.yml.example-mini
@@ -0,0 +1,43 @@
+# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
+# (see: https://github.com/epics-base/ci-scripts)
+
+# This is YAML - indentation levels are crucial
+
+# Set the 'name:' properties to values that work for you
+
+name: MYMODULE ci-scripts build
+
+# Trigger on pushes and PRs to any branch
+on: [push, pull_request]
+
+env:
+ SETUP_PATH: .ci-local:.ci
+ SET: test01
+ CMP: gcc
+
+jobs:
+ build-linux:
+ name: ${{ matrix.base }} / ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ # Set environment variables from matrix parameters
+ env:
+ CMP: ${{ matrix.cmp }}
+ BCFG: ${{ matrix.configuration }}
+ BASE: ${{ matrix.base }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, ubuntu-18.04]
+ cmp: [gcc]
+ configuration: [default, static]
+ base: ["7.0", "3.15"]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Prepare and compile dependencies
+ run: python cue.py prepare
+ - name: Build main module
+ run: python cue.py build
+ - name: Run main module tests
+ run: python cue.py test
+ - name: Collect and show test results
+ run: python cue.py test-results