![Version][badge.version] ![Travis status][badge.travis] ![AppVeyor status][badge.appveyor] ![GitHub Actions status][badge.gh-actions] # Continuous Integration for EPICS Modules The scripts inside this repository are intended to provide a common, easy-to-use and flexible way to add Continuous Integration to EPICS software modules, e.g. Device or Driver Support modules. By including this repository as a Git Submodule, you will be able to use the same flexible, powerful CI setup that EPICS Bases uses, including a way to specify sets of dependent modules (with versions) that you want to compile your module against. By using the submodule mechanism, your module will always use an explicit commit, i.e. a fixed version of the scripts. This ensures that any further development of the ci-scripts will never break your existing use. ## This Repository 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 The example files are your best reference. They are kept up-to-date and show a fully-featured and a minimal setup. You are welcome to use the test suite as a secondary reference, but keep in 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, the test suite does not show the same quality and documentation levels as the example files. ## Features - Compile against different branches or releases of EPICS Base and additional dependencies (modules like asyn, std, sequencer, etc.). - Define setup files that declare sets of dependencies with their versions and locations. - 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 shared (default) or static builds (for executables and libraries). - Define optimized (default) or debug builds. - 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) - 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 **[ci-scripts on Travis-CI README](travis/README.md)** for more details. ### [AppVeyor](https://www.appveyor.com/) - One parallel runner (all builds are sequential) - 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. 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](github-actions/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/), ...). GitHub Actions does not require a separate account. (More details in the specific README of the subdirectory.) 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 ``` 3. Create setup files for different sets of dependencies you want to compile against. (See below.) E.g., a setup file `stable.set` specifying ``` MODULES=sncseq asyn BASE=3.15 ASYN=R4-34 SNCSEQ=R2-2-8 ``` 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 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 and editing it to include the jobs you want the service to run. Use your setup by defining e.g. `SET=stable` in the environment of a job. 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. (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 (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 "version space". One for the oldest versions you want to support, one or two 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 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 ` (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 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. `MODULES=` should list the dependencies (software modules) 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 from the main configuration file by setting `ADD_MODULES` for the specific job(s). `REPOOWNER=` sets the default GitHub owner (or organization) for all dependency modules. Useful if you want to compile against a complete set of dependencies forked into your private GitHub area. For any module mentioned as `foo` in the `MODULES` setting (and for `BASE`), the following settings can be configured: `FOO=` Set version of the module that should be used. Must either be a *tag* name or a *branch* name. [default: `master`] `FOO_REPONAME=` Set the name of the remote repository as `.git`. [default is the slug in lower case: `foo`] `FOO_REPOOWNER=` Set the name of the GitHub owner (or organization) that the module repository can be found under. `FOO_REPOURL=""` Set the complete URL of the remote repository. Useful for dependencies that are not hosted on GitHub. The default URL for the repository is pointing to GitHub, under `$FOO_REPOOWNER` else `$REPOOWNER` else `epics-modules`, using `$FOO_REPONAME` else `foo` and the extension`.git`. `FOO_DEPTH=` Set the depth of the git clone operation. Use 0 for a full clone. [default: 5] `FOO_RECURSIVE=YES/NO` Set to `NO` (or `0`) for a flat clone without recursing into submodules. [default is including submodules: `YES`] `FOO_DIRNAME=` Set the local directory name for the checkout. This will be always be extended by the release or branch name as `-`. [default is the slug in lower case: `foo`] `FOO_HOOK=