Compare commits
75 Commits
PSI-7.0.4.
...
3.15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7826646c0 | ||
|
|
f103a0b376 | ||
|
|
a249561677 | ||
|
|
96887926bf | ||
|
|
c8647ffab7 | ||
|
|
4b884c15b1 | ||
|
|
0ace4e4a30 | ||
|
|
3cf2d3737f | ||
|
|
7c168f20f4 | ||
|
|
5cddcea829 | ||
|
|
9b69e63a69 | ||
|
|
422513990e | ||
|
|
3313860691 | ||
|
|
2b8eb97b79 | ||
|
|
9842bd1b20 | ||
|
|
e7ea81c7a2 | ||
|
|
c528948f45 | ||
|
|
00e9ecf7b5 | ||
|
|
65b34874bd | ||
|
|
939d84f31a | ||
|
|
67fcd65656 | ||
|
|
3be67aca3c | ||
|
|
ebf4a155d7 | ||
|
|
28531b0dbb | ||
|
|
5c3ecf9054 | ||
|
|
e8c5748f89 | ||
|
|
857527280b | ||
|
|
d1ddbad053 | ||
|
|
b55c019f10 | ||
|
|
31584e52be | ||
|
|
2eb5af3167 | ||
|
|
fa069b0845 | ||
|
|
c78db512f2 | ||
|
|
29e9843056 | ||
|
|
0c4ab7b24a | ||
|
|
d831c2b384 | ||
|
|
34d06b6e36 | ||
|
|
b2f7f4e173 | ||
|
|
3c7fb7990f | ||
|
|
c359b49aed | ||
|
|
c140a0a804 | ||
|
|
0bc2a3e999 | ||
|
|
8e7702c8a5 | ||
|
|
5f94ab6d9f | ||
|
|
6ac10d43b1 | ||
|
|
c6af4a245d | ||
|
|
9184983cf0 | ||
|
|
30172226f9 | ||
|
|
2ea0994507 | ||
|
|
dd9f38d711 | ||
|
|
d997690aa5 | ||
|
|
a043599e18 | ||
|
|
02be10069e | ||
|
|
ff4317d05a | ||
|
|
63919e199c | ||
|
|
518bab9675 | ||
|
|
a8036d7f34 | ||
|
|
436ce4526b | ||
|
|
9ba0081a82 | ||
|
|
c60056d4d6 | ||
|
|
68c056f2f8 | ||
|
|
48a6d2f781 | ||
|
|
79bb9e000b | ||
|
|
c404eb3f83 | ||
|
|
7beb32e209 | ||
|
|
a365de2419 | ||
|
|
2035fc641a | ||
|
|
d25c9a74ad | ||
|
|
7632c355ee | ||
|
|
4730e14cc7 | ||
|
|
c969f05f51 | ||
|
|
3947b9a061 | ||
|
|
228ad79b7a | ||
|
|
bbc0a56d2b | ||
|
|
ad3728d00d |
@@ -1,5 +1,12 @@
|
||||
# .appveyor.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
# Appveyor configuration file for EPICS Base 3.15 builds
|
||||
# (see also https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
# whitelist
|
||||
only:
|
||||
- 3.15
|
||||
- /R3\.15\.\d+.*/
|
||||
|
||||
# Version format
|
||||
version: base-{branch}-{build}
|
||||
@@ -29,7 +36,8 @@ clone_depth: 5
|
||||
skip_commits:
|
||||
files:
|
||||
- 'documentation/*'
|
||||
- 'templates/*'
|
||||
- 'startup/*'
|
||||
- '.github/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
@@ -37,6 +45,8 @@ skip_commits:
|
||||
# build matrix configuration #
|
||||
#---------------------------------#
|
||||
|
||||
image: Visual Studio 2015
|
||||
|
||||
# Build Configurations: dll/static, regular/debug
|
||||
configuration:
|
||||
- dynamic
|
||||
@@ -49,6 +59,7 @@ environment:
|
||||
# common / default variables for all jobs
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
BASE: SELF
|
||||
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||
|
||||
matrix:
|
||||
- CMP: vs2019
|
||||
@@ -59,7 +70,7 @@ environment:
|
||||
- CMP: vs2013
|
||||
- CMP: vs2012
|
||||
- CMP: vs2010
|
||||
- CMP: mingw
|
||||
- CMP: gcc
|
||||
|
||||
# Platform: processor architecture
|
||||
platform:
|
||||
@@ -74,14 +85,17 @@ matrix:
|
||||
CMP: vs2012
|
||||
- platform: x64
|
||||
CMP: vs2010
|
||||
- platform: x64
|
||||
CMP: vs2008
|
||||
# Exclude more jobs to reduce build time
|
||||
# Skip 32-bit for "middle-aged" compilers
|
||||
- platform: x86
|
||||
CMP: vs2017
|
||||
- platform: x86
|
||||
CMP: vs2015
|
||||
# MinGW debug builds use the same libraries, unlike VS
|
||||
- configuration: dynamic-debug
|
||||
CMP: gcc
|
||||
- configuration: static-debug
|
||||
CMP: gcc
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
@@ -89,17 +103,17 @@ matrix:
|
||||
|
||||
install:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: python .ci/appveyor/do.py prepare
|
||||
- cmd: python .ci/cue.py prepare
|
||||
|
||||
build_script:
|
||||
- cmd: python .ci/appveyor/do.py build
|
||||
- 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 build test-results -s
|
||||
|
||||
#---------------------------------#
|
||||
# debugging #
|
||||
2
.ci
2
.ci
Submodule .ci updated: e91a588370...20f8e05393
143
.github/workflows/ci-scripts-build.yml
vendored
Normal file
143
.github/workflows/ci-scripts-build.yml
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
# .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
|
||||
|
||||
# Workflow name, shared by all branches
|
||||
|
||||
name: Base
|
||||
|
||||
# Trigger on pushes and PRs to any branch
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'documentation/*'
|
||||
- 'startup/*'
|
||||
- '.appveyor/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'documentation/*'
|
||||
- 'startup/*'
|
||||
- '.appveyor/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
env:
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
BASE: SELF
|
||||
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||
|
||||
jobs:
|
||||
build-base:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
WINE: ${{ matrix.wine }}
|
||||
RTEMS: ${{ matrix.rtems }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
wine: "64"
|
||||
name: "Ub-20 gcc-9 + MinGW"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
wine: "64"
|
||||
name: "Ub-20 gcc-9 + MinGW, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
name: "Ub-20 gcc-9 C++11, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
name: "Ub-20 clang-10 C++11"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
rtems: "4.10"
|
||||
name: "Ub-20 gcc-9 + RT-4.10"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
rtems: "4.9"
|
||||
name: "Ub-20 gcc-9 + RT-4.9"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc-8
|
||||
utoolchain: true
|
||||
configuration: default
|
||||
name: "Ub-20 gcc-8"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
name: "Ub-20 clang-10"
|
||||
|
||||
- os: macos-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
name: "MacOS clang-12"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: default
|
||||
name: "Win2019 MSC-19"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: static
|
||||
name: "Win2019 MSC-19, static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: "apt-get install"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||
if: runner.os == 'Linux'
|
||||
- name: "apt-get install ${{ matrix.cmp }}"
|
||||
run: |
|
||||
export GCC_NAME="${{ matrix.cmp }}"
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install software-properties-common
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install g++-${GCC_NAME#gcc-}
|
||||
if: matrix.utoolchain
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python .ci/cue.py test
|
||||
- name: Upload tapfiles Artifact
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tapfiles ${{ matrix.name }}
|
||||
path: '**/O.*/*.tap'
|
||||
if-no-files-found: ignore
|
||||
- name: Collect and show test results
|
||||
if: ${{ always() }}
|
||||
run: python .ci/cue.py test-results
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,7 +7,6 @@
|
||||
/include/
|
||||
/templates/
|
||||
/configure/*.local
|
||||
/.tests-failed
|
||||
O.*/
|
||||
/QtC-*
|
||||
*.orig
|
||||
|
||||
93
.travis.yml
93
.travis.yml
@@ -1,93 +0,0 @@
|
||||
# .travis.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
dist: xenial
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
|
||||
env:
|
||||
global:
|
||||
- SETUP_PATH=.ci-local:.ci
|
||||
- BASE=SELF
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# for all EPICS builds
|
||||
- libreadline6-dev
|
||||
- libncurses5-dev
|
||||
- perl
|
||||
# for clang compiler
|
||||
- clang
|
||||
# for mingw builds (32bit and 64bit)
|
||||
- g++-mingw-w64-i686
|
||||
- g++-mingw-w64-x86-64
|
||||
# for RTEMS cross builds
|
||||
- qemu-system-x86
|
||||
homebrew:
|
||||
packages:
|
||||
# for all EPICS builds
|
||||
- bash
|
||||
update: true
|
||||
|
||||
install:
|
||||
- ./.ci/travis/prepare.sh
|
||||
|
||||
script:
|
||||
- ./.ci/travis/build.sh
|
||||
|
||||
# Define build jobs
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
# Different configurations of default gcc and clang
|
||||
# (the DIST settings are just FYI on the travis-ci.org site)
|
||||
- dist: bionic
|
||||
env: DIST=bionic
|
||||
|
||||
- env: DIST=xenial
|
||||
|
||||
- dist: bionic
|
||||
env: DIST=bionic EXTRA="CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- dist: trusty
|
||||
env: DIST=trusty STATIC=YES EXTRA="CMD_CXXFLAGS=-std=c++11"
|
||||
|
||||
- dist: bionic
|
||||
compiler: clang
|
||||
env: DIST=bionic
|
||||
|
||||
- compiler: clang
|
||||
env: DIST=xenial
|
||||
|
||||
- dist: trusty
|
||||
compiler: clang
|
||||
env: DIST=trusty STATIC=YES
|
||||
|
||||
# Cross-compilations to Windows using MinGW and WINE
|
||||
|
||||
- env: WINE=32 TEST=NO STATIC=YES
|
||||
compiler: mingw
|
||||
|
||||
- env: WINE=32 TEST=NO STATIC=NO
|
||||
compiler: mingw
|
||||
|
||||
# Cross-compilation to RTEMS
|
||||
|
||||
- env: RTEMS=4.10 TEST=NO
|
||||
|
||||
- env: RTEMS=4.9 TEST=NO
|
||||
|
||||
# MacOS build
|
||||
|
||||
- os: osx
|
||||
env:
|
||||
- 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
|
||||
@@ -71,7 +71,7 @@ FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
|
||||
|
||||
#-------------------------------------------------------
|
||||
# tools for installing libraries and products
|
||||
INSTALL_QUIETLY := $(if $(findstring s,$(MFLAGS)),-q,)
|
||||
INSTALL_QUIETLY := $(if $(filter -s,$(MFLAGS)),-q,)
|
||||
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(INSTALL_QUIETLY)
|
||||
INSTALL_PRODUCT = $(INSTALL)
|
||||
INSTALL_LIBRARY = $(INSTALL)
|
||||
@@ -83,12 +83,18 @@ REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Tools for testing
|
||||
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
|
||||
PROVE = $(PERL) $(TOOLS)/epicsProve.pl
|
||||
PROVE.tap = $(PROVE) --ext .tap --exec "$(CAT)"
|
||||
TAPS_FAILED_LOG = .taps-failed.log
|
||||
TESTS_FAILED_LOG = .tests-failed.log
|
||||
TESTS_FAILED_PATH = $(abspath $(TOP)/$(TESTS_FAILED_LOG))
|
||||
|
||||
TEST_FAILURE_FILE = $(TOP)/.tests-failed
|
||||
PROVE_FAILURE = echo $(abspath .)>> $(TEST_FAILURE_FILE)
|
||||
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
|
||||
PROVE = $(PERL) $(TOOLS)/epicsProve.pl --failures --color
|
||||
PROVE.tap = $(PROVE) --ext .tap --exec "$(CAT)"
|
||||
TESTFAILURES = $(PERL) $(TOOLS)/testFailures.pl
|
||||
SHOWTESTFAILURES = $(TESTFAILURES) $(TESTS_FAILED_PATH) $(TAPS_FAILED_LOG)
|
||||
|
||||
PROVE_FAILURE = echo $(abspath .)>> $(TESTS_FAILED_PATH)
|
||||
TAPFILE_FAILURE = echo $@>> $(TAPS_FAILED_LOG)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# private versions of lex/yacc from EPICS
|
||||
|
||||
@@ -27,7 +27,7 @@ EPICS_VERSION = 3
|
||||
EPICS_REVISION = 15
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 8
|
||||
EPICS_MODIFICATION = 9
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
@@ -35,10 +35,6 @@ EPICS_PATCH_LEVEL = 1
|
||||
|
||||
# This will end in -DEV between official releases
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc1
|
||||
#EPICS_DEV_SNAPSHOT=-rc1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
@@ -80,9 +80,9 @@ COMMON_DIR = ../O.Common
|
||||
IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Make echo output - suppress echoing if make's '-s' flag is set
|
||||
# Make echo output - suppress echoing if '-s' flag was given
|
||||
NOP = :
|
||||
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
|
||||
ECHO = @$(if $(filter -s,$(MFLAGS)),$(NOP),echo)
|
||||
|
||||
#-------------------------------------------------------
|
||||
ifdef T_A
|
||||
|
||||
@@ -159,7 +159,7 @@ cleanArchTargets = $(foreach arch,$(BUILD_ARCHS), clean$(DIVIDER)$(arch))
|
||||
-include $(TOP)/configure/CONFIG_APP_INCLUDE
|
||||
|
||||
all: install
|
||||
ifeq ($(EPICS_HOST_ARCH),$T_A)
|
||||
ifeq ($(EPICS_HOST_ARCH),$(T_A))
|
||||
host: install
|
||||
else
|
||||
# Do nothing
|
||||
@@ -187,7 +187,8 @@ endif
|
||||
|
||||
##################################################### build dependancies, clean rule
|
||||
|
||||
inc : $(COMMON_INC) $(INSTALL_INC)
|
||||
inc : $(COMMON_INC) $(INSTALL_INC) $(COMMON_DBDS) $(COMMON_DBDCATS) \
|
||||
$(INSTALL_DBDS) $(INSTALL_DBD_INSTALLS)
|
||||
|
||||
build : $(COMMON_DBDS) $(COMMON_DBS) $(COMMON_DBDCATS) \
|
||||
$(INSTALL_DBDS) $(INSTALL_DBS) \
|
||||
@@ -428,26 +429,26 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file))))
|
||||
##################################################### HTML files
|
||||
|
||||
$(COMMON_DIR)/%.html: %.dbd.pod $(TOOLS)/dbdToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
@$(RM) $@ $(notdir $@)
|
||||
$(PERL) $(TOOLS)/dbdToHtml.pl $(DBDFLAGS) -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.html: %.pod $(TOOLS)/podToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
@$(RM) $@ $(notdir $@)
|
||||
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
@$(RM) $@ $(notdir $@)
|
||||
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
@$(RM) $@ $(notdir $@)
|
||||
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
.PRECIOUS: $(COMMON_DIR)/%.html %.html
|
||||
.PRECIOUS: $(COMMON_DIR)/%.html
|
||||
|
||||
##################################################### DB files
|
||||
|
||||
|
||||
@@ -86,17 +86,20 @@ endif
|
||||
#---------------------------------------------------------------
|
||||
# Include defines and rules for prod, library and test* targets
|
||||
|
||||
#ifneq (,$(strip $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) $(LOADABLE_LIBRARY) ))
|
||||
ifneq (,$(strip $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) \
|
||||
$(LOADABLE_LIBRARY)))
|
||||
include $(CONFIG)/RULES_TARGET
|
||||
#endif
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Read dependency files
|
||||
|
||||
ifneq (inc,$(strip $(MAKECMDGOALS)))
|
||||
ifneq (,$(strip $(HDEPENDS_FILES)))
|
||||
$(filter-out $(wildcard *$(DEP)), $(HDEPENDS_FILES)): | $(COMMON_INC)
|
||||
-include $(HDEPENDS_FILES)
|
||||
endif
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Products and Object libraries
|
||||
@@ -144,14 +147,14 @@ build: inc
|
||||
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \
|
||||
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
|
||||
|
||||
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS)
|
||||
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS) \
|
||||
$(INSTALL_HTMLS)
|
||||
|
||||
buildInstall : \
|
||||
$(INSTALL_SCRIPTS) $(INSTALL_PROD) $(INSTALL_MUNCHS) \
|
||||
$(INSTALL_TCLLIBS) $(INSTALL_TCLINDEX) \
|
||||
$(INSTALL_OBJS) \
|
||||
$(INSTALL_DOCS) \
|
||||
$(INSTALL_HTMLS) \
|
||||
$(INSTALL_TEMPLATE) \
|
||||
$(INSTALL_BIN_INSTALLS)
|
||||
|
||||
@@ -339,7 +342,8 @@ runtests: run-tap-tests
|
||||
run-tap-tests: $(TESTSCRIPTS.t)
|
||||
ifneq ($(TESTSCRIPTS.t),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
$(PROVE) --failures --color $^ || $(PROVE_FAILURE)
|
||||
$(ECHO) "$(PROVE) $^"
|
||||
@$(PROVE) $^ || $(PROVE_FAILURE)
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -350,7 +354,8 @@ test-results: tap-results
|
||||
tap-results: $(TAPFILES)
|
||||
ifneq ($(strip $(TAPFILES)),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
$(PROVE.tap) --failures --color $^ || $(PROVE_FAILURE)
|
||||
$(ECHO) "$(PROVE.tap) $^"
|
||||
@$(PROVE.tap) $^ || $(PROVE_FAILURE)
|
||||
endif
|
||||
|
||||
CURRENT_TAPFILES := $(wildcard $(TAPFILES))
|
||||
@@ -358,8 +363,8 @@ CURRENT_JUNITFILES := $(wildcard $(JUNITFILES))
|
||||
endif
|
||||
|
||||
clean-tests:
|
||||
ifneq ($(CURRENT_TAPFILES),)
|
||||
$(RM) $(CURRENT_TAPFILES)
|
||||
ifneq ($(CURRENT_TAPFILES)$(TAPS_FAILED_LOG),)
|
||||
$(RM) $(CURRENT_TAPFILES) $(TAPS_FAILED_LOG)
|
||||
endif
|
||||
ifneq ($(CURRENT_JUNITFILES),)
|
||||
$(RM) $(CURRENT_JUNITFILES)
|
||||
@@ -368,7 +373,8 @@ endif
|
||||
# A .tap file is the output from running the associated test script
|
||||
$(TAPFILES.t): %.tap: %.t
|
||||
ifdef RUNTESTS_ENABLED
|
||||
-$(PERL) $< -tap > $@
|
||||
$(ECHO) "$(PERL) $< -tap > $@"
|
||||
@$(PERL) $< -tap > $@ || $(TAPFILE_FAILURE)
|
||||
endif
|
||||
|
||||
$(JUNITFILES.t): %-results.xml: %.tap
|
||||
@@ -492,6 +498,10 @@ $(INSTALL_DOC)/%: ../%
|
||||
$(ECHO) "Installing doc $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(INSTALL_DOC)
|
||||
|
||||
$(INSTALL_HTML)/$(HTMLS_DIR)/%: $(COMMON_DIR)/%
|
||||
$(ECHO) "Installing generated html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
$(INSTALL_HTML)/$(HTMLS_DIR)/%: %
|
||||
$(ECHO) "Installing html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
@@ -500,10 +510,6 @@ $(INSTALL_HTML)/$(HTMLS_DIR)/%: ../%
|
||||
$(ECHO) "Installing html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
$(INSTALL_HTML)/$(HTMLS_DIR)/%: $(COMMON_DIR)/%
|
||||
$(ECHO) "Installing generated html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
$(INSTALL_TEMPLATES_SUBDIR)/%: ../%
|
||||
$(ECHO) "Installing $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
@@ -33,8 +33,10 @@ expand_clean:
|
||||
ASSEMBLE_TOOL ?= $(PERL) $(TOOLS)/assembleSnippets.pl
|
||||
|
||||
define COMMON_ASSEMBLY_template
|
||||
ifneq '$$($1_PATTERN)' ''
|
||||
$1_SNIPPETS += $$(foreach dir, .. $$(SRC_DIRS), \
|
||||
$$(wildcard $$(dir)/$$($1_PATTERN)))
|
||||
endif
|
||||
$(COMMON_DIR)/$1: $$($1_SNIPPETS)
|
||||
$(ECHO) "Assembling common file $$@ from snippets"
|
||||
@$(RM) $1
|
||||
@@ -45,8 +47,10 @@ $(foreach asy, $(COMMON_ASSEMBLIES), \
|
||||
$(eval $(call COMMON_ASSEMBLY_template,$(strip $(asy)))))
|
||||
|
||||
define ASSEMBLY_template
|
||||
ifneq '$$($1_PATTERN)' ''
|
||||
$1_SNIPPETS += $$(foreach dir, .. $$(SRC_DIRS), \
|
||||
$$(wildcard $$(dir)/$$($1_PATTERN)))
|
||||
endif
|
||||
$1: $$($1_SNIPPETS)
|
||||
$(ECHO) "Assembling file $$@ from snippets"
|
||||
@$(RM) $$@
|
||||
|
||||
@@ -26,7 +26,6 @@ $(foreach target, $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) $(LOADABLE_LIBRA
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# This define block requires GNU make 3.81
|
||||
define PROD_template
|
||||
ifeq ($$(strip $$($(1)_OBJS) $$($(1)_SRCS) $$(PRODUCT_OBJS)),)
|
||||
$(1)_OBJS = $(1)$$(OBJ)
|
||||
|
||||
@@ -37,15 +37,15 @@ uninstall$(DIVIDER)%:
|
||||
|
||||
before-runtests before-test-results: rm-failure-file
|
||||
rm-failure-file:
|
||||
@$(RM) $(TEST_FAILURE_FILE)
|
||||
@$(RM) $(TESTS_FAILED_PATH)
|
||||
runtests test-results:
|
||||
$(PERL) $(TOOLS)/testFailures.pl $(TEST_FAILURE_FILE)
|
||||
$(SHOWTESTFAILURES)
|
||||
|
||||
help:
|
||||
@echo "Usage: gnumake [options] [target] ..."
|
||||
@echo "Targets supported by all Makefiles:"
|
||||
@echo " all - Same as install (default rule)"
|
||||
@echo " inc - Installs header files"
|
||||
@echo " inc - Installs header, dbd and html files"
|
||||
@echo " build - Builds and installs all targets"
|
||||
@echo " install - Builds and installs all targets"
|
||||
@echo " buildInstall - Same as install (deprecated)"
|
||||
|
||||
@@ -72,7 +72,7 @@ CPPFLAGS += $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\
|
||||
$(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\
|
||||
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
|
||||
|
||||
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
|
||||
ECHO = @$(if $(filter -s,$(MFLAGS)),$(NOP),echo)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Although RTEMS uses gcc, it wants to use gcc its own way
|
||||
|
||||
14
configure/os/CONFIG.Common.darwin-aarch64
Normal file
14
configure/os/CONFIG.Common.darwin-aarch64
Normal file
@@ -0,0 +1,14 @@
|
||||
# CONFIG.Common.darwin-aarch64
|
||||
#
|
||||
# This file is maintained by the build community.
|
||||
#
|
||||
# Definitions for darwin-aarch64 target builds
|
||||
# Sites may override these definitions in CONFIG_SITE.Common.darwin-aarch64
|
||||
#-------------------------------------------------------
|
||||
|
||||
#
|
||||
# To build universal binaries, configure ARCH_CLASS
|
||||
# in the file CONFIG_SITE.Common.darwin-aarch64
|
||||
|
||||
# Include definitions common to all Darwin targets
|
||||
include $(CONFIG)/os/CONFIG.darwinCommon.darwinCommon
|
||||
8
configure/os/CONFIG.darwin-aarch64.Common
Normal file
8
configure/os/CONFIG.darwin-aarch64.Common
Normal file
@@ -0,0 +1,8 @@
|
||||
# CONFIG.darwin-aarch64.Common
|
||||
#
|
||||
# Definitions for darwin-aarch64 host builds
|
||||
# Sites may override these definitions in CONFIG_SITE.darwin-aarch64.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to unix hosts
|
||||
include $(CONFIG)/os/CONFIG.UnixCommon.Common
|
||||
@@ -49,9 +49,9 @@ OPT_CFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CFLAGS_YES = $(OPT_CFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Zi generate program database for debugging information
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CFLAGS_NO = -Zi -RTCsu
|
||||
OPT_CFLAGS_NO = -Z7 -RTCsu
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CFLAG = -Fo
|
||||
@@ -116,9 +116,9 @@ OPT_CXXFLAGS_YES_NO = -Ox -Oy-
|
||||
OPT_CXXFLAGS_YES = $(OPT_CXXFLAGS_YES_$(OPT_WHOLE_PROGRAM))
|
||||
|
||||
#
|
||||
# -Zi generate program database for debugging information
|
||||
# -Z7 generate C7 compatible debugging information (inside .obj)
|
||||
# -RTCsu enable run-time error checks
|
||||
OPT_CXXFLAGS_NO = -RTCsu -Zi
|
||||
OPT_CXXFLAGS_NO = -RTCsu -Z7
|
||||
|
||||
# specify object file name and location
|
||||
OBJ_CXXFLAG = -Fo
|
||||
@@ -140,20 +140,6 @@ STATIC_LDLIBS_NO=
|
||||
STATIC_LDFLAGS=
|
||||
RANLIB=
|
||||
|
||||
#
|
||||
# option needed for parallel builds with Visual Studio 2013 onward
|
||||
# VS2012 and above have VisualStudioVersion, so just need to exclude 2012 (11.0)
|
||||
# -FS Force Synchronous PDB Writes
|
||||
#
|
||||
ifneq ($(VisualStudioVersion),)
|
||||
ifneq ($(VisualStudioVersion),11.0)
|
||||
OPT_CXXFLAGS_NO += -FS
|
||||
OPT_CFLAGS_NO += -FS
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# add -profile here to run the ms profiler
|
||||
# -LTCG whole program optimization
|
||||
# -incremental:no full linking
|
||||
|
||||
9
configure/os/CONFIG_SITE.Common.darwin-aarch64
Normal file
9
configure/os/CONFIG_SITE.Common.darwin-aarch64
Normal file
@@ -0,0 +1,9 @@
|
||||
# CONFIG_SITE.Common.darwin-aarch64
|
||||
#
|
||||
# Site override definitions for darwin-aarch64 target builds
|
||||
#-------------------------------------------------------
|
||||
|
||||
#
|
||||
# arm64 devices: Apple Silicon M1
|
||||
|
||||
ARCH_CLASS = arm64
|
||||
@@ -1,184 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Installation notes for EPICS on Mac OS X (Darwin)</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<h1>Building EPICS base</h1>
|
||||
<ul>
|
||||
<li>
|
||||
To build base:
|
||||
<ol>
|
||||
<li>
|
||||
Set the EPICS_HOST_ARCH environment variable to darwin-ppc, darwin-x86 or darwin-ppcx86.
|
||||
The scripts in the
|
||||
base/startup directory can automate this. For example, here's part
|
||||
of my Bash login script (~/.bash_login):
|
||||
<pre>
|
||||
#
|
||||
# EPICS
|
||||
#
|
||||
EPICS_BASE="${HOME}/src/EPICS/base"
|
||||
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
|
||||
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
<code>cd</code> to the EPICS base top-level source directory.
|
||||
</li>
|
||||
<li>
|
||||
Uncomment the appropriate line in the relevent
|
||||
EPICS_BASE/configure/os/CONFIG_SITE.Common.darwin-xxx file for your EPICS_HOST_ARCH value.
|
||||
Newer versions of OS X (e.g. Snow Leopard) may include only 64 bit versions of some OS libraries,
|
||||
so should only have the x86_64 ARCH_CLASS.
|
||||
</li>
|
||||
<li>
|
||||
Run <code>make</code>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
As distributed, EPICS on Mac OS X uses the readline command line input
|
||||
routines. IOC applications are more pleasant to interact with if
|
||||
either the readline or libtecla library is used. The easiest
|
||||
way to get either or both of these libraries on to your system is to
|
||||
download and install them using the either the DarwinPorts
|
||||
distribution or the Fink package manager. If you don't want to install
|
||||
the readline library, set the COMMANDLINE_LIBRARY variable in one of
|
||||
the CONFIG_SITE files to EPICS.
|
||||
<p>
|
||||
Information on DarwinPorts is available from
|
||||
<a href="http://www.opendarwin.org/projects/darwinports/">the DarwinPorts
|
||||
project page</a>.
|
||||
DarwinPorts binary packages are available from
|
||||
<a href="http://packages.opendarwin.org/">here</a>.
|
||||
<p>
|
||||
Fink may be downloaded from
|
||||
<a href="http://fink.sourceforge.net/">the Source Forge</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If broadcasts are not seen locally, try adding "localhost" (127.0.0.1)
|
||||
to the EPICS_CA_ADDR_LIST.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h1>Building EPICS extensions</h1>
|
||||
<p>
|
||||
Many extensions build and run properly on OS X. To build and run medm, first
|
||||
obtain the X11 run-time and developer packages from Apple and the OpenMotif3
|
||||
package from Fink.
|
||||
|
||||
<h1>Objective-C and AppleScript</h1>
|
||||
<p>
|
||||
Code written in Objective-C can be included in host or IOC applications.
|
||||
Here are a couple of short Objective-C examples which can be used to send
|
||||
AppleScript events to other applications on the OS X machine.
|
||||
|
||||
<pre>
|
||||
/*
|
||||
* exampleAppleScriptRecord.m
|
||||
*
|
||||
* Simple Objective-C/AppleScript subroutine record
|
||||
*
|
||||
* To use this record in an application:
|
||||
*
|
||||
* 1) Make the following changes to the application Makefile:
|
||||
* - Add exampleAppleScriptRecord.m to the application SRCS.
|
||||
* - Add -framework Foundation to the application LDFLAGS.
|
||||
* 2) Add the following line to the application database description:
|
||||
* registrar(registerExampleAppleScript)
|
||||
* 3) Add a record to the application database:
|
||||
* record(sub,"setVolume")
|
||||
* {
|
||||
* field(SNAM,"exampleAppleScriptProcess")
|
||||
* }
|
||||
*/
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <registryFunction.h>
|
||||
#include <subRecord.h>
|
||||
#include <alarm.h>
|
||||
#include <errlog.h>
|
||||
#include <recGbl.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
/*
|
||||
* Shim between EPICS and NSAppleScript class.
|
||||
*/
|
||||
static long
|
||||
exampleAppleScriptProcess(struct subRecord *psub)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSDictionary *err;
|
||||
NSAppleScript *nsa;
|
||||
|
||||
nsa = [[NSAppleScript alloc] initWithSource:[NSString stringWithFormat:
|
||||
@"tell application \"Finder\" to set volume %g\n", psub->a]];
|
||||
if ([nsa executeAndReturnError:&err] == nil) {
|
||||
errlogPrintf("Failed to run AppleScript: %s\n",
|
||||
[[err objectForKey:NSAppleScriptErrorMessage] cString]);
|
||||
recGblSetSevr(psub, SOFT_ALARM, INVALID_ALARM);
|
||||
}
|
||||
[nsa release];
|
||||
[pool release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static registryFunctionRef subRef[] = {
|
||||
{"exampleAppleScriptProcess",(REGISTRYFUNCTION)exampleAppleScriptProcess}
|
||||
};
|
||||
|
||||
static void registerExampleAppleScript(void)
|
||||
{
|
||||
registryFunctionRefAdd(subRef,NELEMENTS(subRef));
|
||||
}
|
||||
epicsExportRegistrar(registerExampleAppleScript);
|
||||
|
||||
|
||||
==============================================================================
|
||||
/*
|
||||
* runAppleScript.m
|
||||
*
|
||||
* Simple Objective-C/AppleScript shim to allow EPICS application to
|
||||
* send arbitrary AppleScript messages to other applications.
|
||||
*
|
||||
* To use this subroutine in an application make the following
|
||||
* changes to the application Makefile:
|
||||
* - Add runAppleScript.m to the application SRCS.
|
||||
* - Add -framework Foundation to the application LDFLAGS.
|
||||
*/
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <errlog.h>
|
||||
|
||||
int
|
||||
runAppleScript(const char *format, ...)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *script;
|
||||
NSMutableDictionary *err;
|
||||
NSAppleScript *nsa;
|
||||
va_list args;
|
||||
int ret = 0;
|
||||
|
||||
va_start(args, format);
|
||||
script = [[NSString alloc] initWithFormat:
|
||||
[NSString stringWithCString:format] arguments:args];
|
||||
va_end(args);
|
||||
err = [NSMutableDictionary dictionaryWithCapacity:10];
|
||||
nsa = [[NSAppleScript alloc] initWithSource:script];
|
||||
if ([nsa executeAndReturnError:&err] == nil) {
|
||||
errlogPrintf("Failed to run AppleScript: %s\n",
|
||||
[[err objectForKey:NSAppleScriptErrorMessage] cString]);
|
||||
ret = -1;
|
||||
}
|
||||
[script release];
|
||||
[nsa release];
|
||||
[pool release];
|
||||
return ret;
|
||||
}
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,28 +1,28 @@
|
||||
# Installation Instructions
|
||||
|
||||
## EPICS Base Release 3.15.8
|
||||
## EPICS Base Release 3.15.x
|
||||
|
||||
-----
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [What is EPICS base?](#0_0_1)
|
||||
- [What is new in this release?](#0_0_2)
|
||||
- [Copyright](#0_0_3)
|
||||
- [Supported platforms](#0_0_4)
|
||||
- [Supported compilers](#0_0_5)
|
||||
- [Software requirements](#0_0_6)
|
||||
- [Host system storage requirements](#0_0_7)
|
||||
- [Documentation](#0_0_8)
|
||||
- [Directory Structure](#0_0_10)
|
||||
- [Build related components](#0_0_11)
|
||||
- [Building EPICS base (Unix and Win32)](#0_0_12)
|
||||
- [Example application and extension](#0_0_13)
|
||||
- [Multiple host platforms](#0_0_14)
|
||||
- [What is EPICS base?](#what-is-epics-base?)
|
||||
- [What is new in this release?](#what-is-new-in-this-release?)
|
||||
- [Copyright](#copyright)
|
||||
- [Supported platforms](#supported-platforms)
|
||||
- [Supported compilers](#supported-compilers)
|
||||
- [Software requirements](#software-requirements)
|
||||
- [Host system storage requirements](#host-system-storage-requirements)
|
||||
- [Documentation](#documentation)
|
||||
- [Directory Structure](#directory-structure)
|
||||
- [Site-specific build configuration](#site-specific-build-configuration)
|
||||
- [Building EPICS base](#building-epics-base)
|
||||
- [Example application and extension](#example-application-and-extension)
|
||||
- [Multiple host platforms](#multiple-host-platforms)
|
||||
|
||||
-----
|
||||
|
||||
### <span id="0_0_1">What is EPICS base?</span>
|
||||
### What is EPICS base?
|
||||
|
||||
The Experimental Physics and Industrial Control Systems (EPICS) is an
|
||||
extensible set of software components and tools with which application
|
||||
@@ -34,17 +34,17 @@ function. EPICS base allows an arbitrary number of target systems,
|
||||
IOCs (input/output controllers), and host systems, OPIs (operator
|
||||
interfaces) of various types.
|
||||
|
||||
### <span id="0_0_2">What is new in this release?</span>
|
||||
### What is new in this release?
|
||||
|
||||
Please check the `RELEASE_NOTES` file in the distribution for
|
||||
Please check the `documentation/RELEASE_NOTES.md` file for
|
||||
description of changes and release migration details.
|
||||
|
||||
### <span id="0_0_3">Copyright</span>
|
||||
### Copyright
|
||||
|
||||
Please review the LICENSE file included in the distribution for legal
|
||||
terms of usage.
|
||||
Please review the `LICENSE` file included in the distribution for
|
||||
legal terms of usage.
|
||||
|
||||
### <span id="0_0_4">Supported platforms</span>
|
||||
### Supported platforms
|
||||
|
||||
The list of platforms supported by this version of EPICS base is given
|
||||
in the `configure/CONFIG_SITE` file. If you are trying to build EPICS
|
||||
@@ -55,7 +55,7 @@ base/configure/os/directory. You can start by copying existing
|
||||
configuration files in the configure/os directory and then make
|
||||
changes for your new platforms.
|
||||
|
||||
### <span id="0_0_5">Supported compilers</span>
|
||||
### Supported compilers
|
||||
|
||||
This version of EPICS base has been built and tested using the host
|
||||
vendor's C and C++ compilers, as well as the GNU gcc and g++
|
||||
@@ -64,27 +64,32 @@ targets. You may need the C and C++ compilers to be in your search
|
||||
path to do EPICS builds; check the definitions of CC and CCC in
|
||||
`base/configure/os/CONFIG.<host>.<host>` if you have problems.
|
||||
|
||||
### <span id="0_0_6">Software requirements</span>
|
||||
### Software requirements
|
||||
|
||||
**GNU make**
|
||||
You must use GNU make, gnumake, for any EPICS builds. Set your path so
|
||||
that a gnumake version 3.81 or later is available.
|
||||
#### GNU make
|
||||
|
||||
You must use the GNU version of `make` for EPICS builds. Set your path
|
||||
so that version 3.81 or later is available (4.0 or later on Windows).
|
||||
|
||||
#### Perl
|
||||
|
||||
**Perl**
|
||||
You must have Perl version 5.8.1 or later installed. The EPICS
|
||||
configuration files do not specify the perl full pathname, so the perl
|
||||
executable must be found through your normal search path.
|
||||
|
||||
**Unzip and tar (Winzip on WIN32 systems)**
|
||||
#### Unzip and tar (Winzip on WIN32 systems)
|
||||
|
||||
You must have tools available to unzip and untar the EPICS base
|
||||
distribution file.
|
||||
|
||||
**Target systems**
|
||||
#### Target systems
|
||||
|
||||
EPICS supports IOCs running on embedded platforms such as VxWorks and
|
||||
RTEMS built using a cross-compiler, and also supports soft IOCs
|
||||
running as processes on the host platform.
|
||||
|
||||
**vxWorks**
|
||||
#### vxWorks
|
||||
|
||||
You must have vxWorks 5.5.x or 6.x installed if any of your target
|
||||
systems are vxWorks systems; the C++ compiler for vxWorks 5.4 is now
|
||||
too old to support. The vxWorks installation provides the
|
||||
@@ -98,134 +103,148 @@ Consult the [vxWorks 5.x](https://epics.anl.gov/base/tornado.php) or
|
||||
about and the vxWorks documentation for information about configuring
|
||||
your vxWorks operating system for use with EPICS.
|
||||
|
||||
**RTEMS**
|
||||
#### RTEMS
|
||||
|
||||
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or
|
||||
later.
|
||||
4.10.x. RTEMS 5 and above are only supported in EPICS 7.0.6 or later.
|
||||
|
||||
**GNU readline or Tecla library**
|
||||
GNU readline and Tecla libraries can be used by the IOC shell to
|
||||
provide command line editing and command line history recall and edit.
|
||||
GNU readline (or Tecla library) must be installed on your target
|
||||
system when `COMMANDLINE_LIBRARY` is set to READLINE (or TECLA) for
|
||||
that target. EPICS (EPICS shell) is the default specified in
|
||||
`CONFIG_COMMON`. A READLINE override is defined for linux-x86 in the
|
||||
EPICS distribution. Comment out `COMMANDLINE_LIBRARY=READLINE` in
|
||||
`configure/os/CONFIG_SITE.Common.linux-x86` if readline is not
|
||||
installed on linux-x86. Command-line editing and history will then be
|
||||
those supplied by the os. On vxWorks the ledLib command-line input
|
||||
library is used instead.
|
||||
#### Command Line Editing
|
||||
|
||||
### <span id="0_0_7">Host system storage requirements</span>
|
||||
|
||||
The compressed tar file is approximately 1.6 MB in size. The
|
||||
GNU readline and other similar libraries can be used by the IOC shell
|
||||
to provide command line editing and command line history recall. The
|
||||
GNU readline development package (or Apple's emulator on macOS) must
|
||||
be installed for a target when its build configuration variable
|
||||
`COMMANDLINE_LIBRARY` is set to `READLINE`. The default specified in
|
||||
`CONFIG_COMMON` is `EPICS`, but most linux target builds can detect if
|
||||
readline is available and will then use it. RTEMS targets may be
|
||||
configured to use `LIBTECLA` if available, and on vxWorks the OS's
|
||||
ledLib line-editing library is normally used.
|
||||
|
||||
### Host system storage requirements
|
||||
|
||||
The compressed tar file is approximately 1.7 MB in size. The
|
||||
distribution source tree takes up approximately 12 MB. Each host
|
||||
target will need around 40 MB for build files, and each cross-compiled
|
||||
target around 20 MB.
|
||||
target will need around 50 MB for build files, and each cross-compiled
|
||||
target around 30 MB.
|
||||
|
||||
### <span id="0_0_8">Documentation</span>
|
||||
### Documentation
|
||||
|
||||
EPICS documentation is available through the [EPICS
|
||||
website](https://epics.anl.gov/) at Argonne.
|
||||
|
||||
Release specific documentation can also be found in the
|
||||
base/documentation directory of the distribution.
|
||||
`base/documentation` directory of the distribution.
|
||||
|
||||
### <span id="0_0_10">Directory Structure</span>
|
||||
### Directory Structure
|
||||
|
||||
#### Distribution directory structure:
|
||||
#### Distribution directory structure
|
||||
|
||||
```
|
||||
base Root directory of the base distribution
|
||||
base/configure Operating system independent build config files
|
||||
base/configure/os Operating system dependent build config files
|
||||
base/documentation Distribution documentation
|
||||
base/src Source code in various subdirectories
|
||||
base/startup Scripts for setting up path and environment
|
||||
base Root directory of the distribution
|
||||
base/configure Build rules and OS-independent config files
|
||||
base/configure/os OS-dependent build config files
|
||||
base/documentation Distribution documentation
|
||||
base/src Source code in various subdirectories
|
||||
base/startup Scripts for setting up path and environment
|
||||
```
|
||||
|
||||
#### Install directories created by the build:
|
||||
#### Directories created by the build
|
||||
|
||||
These are created in the root directory of the installation (`base`
|
||||
above) or under the directory pointed to by the `INSTALL_LOCATION`
|
||||
configuration variable if that has been set.
|
||||
|
||||
```
|
||||
bin Installed scripts and executables in subdirs
|
||||
cfg Installed build configuration files
|
||||
db Installed data bases
|
||||
dbd Installed data base definitions
|
||||
doc Installed documentation files
|
||||
html Installed html documentation
|
||||
include Installed header files
|
||||
include/os Installed os specific header files in subdirs
|
||||
include/compiler Installed compiler-specific header files
|
||||
lib Installed libraries in arch subdirectories
|
||||
lib/perl Installed perl modules
|
||||
templates Installed templates
|
||||
bin Installed scripts and executables in subdirs
|
||||
cfg Installed build configuration files
|
||||
db Installed database files
|
||||
dbd Installed database definition files
|
||||
html Installed html documentation
|
||||
include Installed header files
|
||||
include/os Installed OS-specific header files in subdirs
|
||||
include/compiler Installed compiler-specific header files
|
||||
lib Installed libraries in arch subdirectories
|
||||
lib/perl Installed perl modules
|
||||
templates Installed templates
|
||||
```
|
||||
|
||||
### <span id="0_0_11">Build related components</span>
|
||||
#### `base/documentation` Directory
|
||||
|
||||
#### base/documentation directory - contains setup, build, and install documents
|
||||
This contains documents on how to setup, build, and install EPICS.
|
||||
|
||||
```
|
||||
README.md Instructions for setup and building epics base
|
||||
README.darwin.html Installation notes for Mac OS X (Darwin)
|
||||
RELEASE_NOTES.html Notes on release changes
|
||||
KnownProblems.html List of known problems and workarounds
|
||||
README.md This file
|
||||
RELEASE_NOTES.md Notes on release changes
|
||||
KnownProblems.html List of known problems and workarounds
|
||||
```
|
||||
|
||||
#### base/startup directory - contains scripts to set environment and path
|
||||
#### `base/startup` Directory
|
||||
|
||||
This contains several example scripts that show how to set up the
|
||||
build environment and PATH for using EPICS. Sites would usually copy and/or modify these files as appropriate for their environment; they are not used by the build system at all.
|
||||
|
||||
```
|
||||
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
|
||||
unix.csh C shell script to set path and env variables
|
||||
unix.sh Bourne shell script to set path and env variables
|
||||
win32.bat Bat file example to configure win32-x86 target
|
||||
windows.bat Bat file example to configure windows-x64 target
|
||||
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
|
||||
unix.csh C shell script to set path and env variables
|
||||
unix.sh Bourne shell script to set path and env variables
|
||||
win32.bat Bat file example to configure win32-x86 target
|
||||
windows.bat Bat file example to configure windows-x64 target
|
||||
```
|
||||
|
||||
#### base/configure directory - contains build definitions and rules
|
||||
#### `base/configure` directory
|
||||
|
||||
This contains build-system files providing definitions and rules
|
||||
required by GNU Make to build EPICS. Users should only need to modify the `CONFIG_SITE` files to configure the EPICS build.
|
||||
|
||||
```
|
||||
CONFIG Includes configure files and allows variable overrides
|
||||
CONFIG.CrossCommon Cross build definitions
|
||||
CONFIG.gnuCommon Gnu compiler build definitions for all archs
|
||||
CONFIG_ADDONS Definitions for <osclass> and DEFAULT options
|
||||
CONFIG_APP_INCLUDE
|
||||
CONFIG_BASE EPICS base tool and location definitions
|
||||
CONFIG_BASE_VERSION Definitions for EPICS base version number
|
||||
CONFIG_COMMON Definitions common to all builds
|
||||
CONFIG_ENV Definitions of EPICS environment variables
|
||||
CONFIG_FILE_TYPE
|
||||
CONFIG_SITE Site specific make definitions
|
||||
CONFIG_SITE_ENV Site defaults for EPICS environment variables
|
||||
MAKEFILE Installs CONFIG* RULES* creates
|
||||
RELEASE Location of external products
|
||||
RULES Includes appropriate rules file
|
||||
RULES.Db Rules for database and database definition files
|
||||
RULES.ioc Rules for application iocBoot/ioc* directory
|
||||
RULES_ARCHS Definitions and rules for building architectures
|
||||
RULES_BUILD Build and install rules and definitions
|
||||
RULES_DIRS Definitions and rules for building subdirectories
|
||||
RULES_EXPAND
|
||||
RULES_FILE_TYPE
|
||||
RULES_TARGET
|
||||
RULES_TOP Rules specific to a <top> dir (uninstall and tar)
|
||||
Sample.Makefile Sample makefile with comments
|
||||
CONFIG Main entry point for building EPICS
|
||||
CONFIG.CrossCommon Cross build definitions
|
||||
CONFIG.gnuCommon Gnu compiler build definitions for all archs
|
||||
CONFIG_ADDONS Definitions for <osclass> and DEFAULT options
|
||||
CONFIG_APP_INCLUDE
|
||||
CONFIG_BASE EPICS base tool and location definitions
|
||||
CONFIG_BASE_VERSION Definitions for EPICS base version number
|
||||
CONFIG_COMMON Definitions common to all builds
|
||||
CONFIG_ENV Definitions of EPICS environment variables
|
||||
CONFIG_FILE_TYPE
|
||||
CONFIG_SITE Site specific make definitions
|
||||
CONFIG_SITE_ENV Site defaults for EPICS environment variables
|
||||
MAKEFILE Installs CONFIG* RULES* creates
|
||||
RELEASE Location of external products
|
||||
RULES Includes appropriate rules file
|
||||
RULES.Db Rules for database and database definition files
|
||||
RULES.ioc Rules for application iocBoot/ioc* directory
|
||||
RULES_ARCHS Definitions and rules for building architectures
|
||||
RULES_BUILD Build and install rules and definitions
|
||||
RULES_DIRS Definitions and rules for building subdirectories
|
||||
RULES_EXPAND
|
||||
RULES_FILE_TYPE
|
||||
RULES_TARGET
|
||||
RULES_TOP Rules specific to a <top> dir only
|
||||
Sample.Makefile Sample makefile with comments
|
||||
```
|
||||
|
||||
#### base/configure/os directory - contains os-arch specific definitions
|
||||
#### `base/configure/os` Directory
|
||||
|
||||
Files in here provide definitions that are shared by or specific to particular host and/or target architectures. Users should only need to modify the `CONFIG_SITE` files in this directory to configure the EPICS build.
|
||||
|
||||
```
|
||||
CONFIG.<host>.<target> Specific host-target build definitions
|
||||
CONFIG.Common.<target> Specific target definitions for all hosts
|
||||
CONFIG.<host>.Common Specific host definitions for all targets
|
||||
CONFIG.UnixCommon.Common Definitions for Unix hosts and all targets
|
||||
CONFIG.Common.UnixCommon Definitions for Unix targets and all hosts
|
||||
CONFIG.Common.vxWorksCommon Specific host definitions for all vx targets
|
||||
CONFIG_SITE.<host>.<target> Site specific host-target definitions
|
||||
CONFIG_SITE.Common.<target> Site specific target defs for all hosts
|
||||
CONFIG_SITE.<host>.Common Site specific host defs for all targets
|
||||
CONFIG.<host>.<target> Definitions for a specific host-target combination
|
||||
CONFIG.Common.<target> Definitions for a specific target, any host
|
||||
CONFIG.<host>.Common Definitions for a specific host, any target
|
||||
CONFIG.UnixCommon.Common Definitions for Unix hosts, any target
|
||||
CONFIG.Common.UnixCommon Definitions for Unix targets, any host
|
||||
CONFIG.Common.RTEMS Definitions for all RTEMS targets, any host
|
||||
CONFIG.Common.vxWorksCommon Definitions for all vxWorks targets, any host
|
||||
CONFIG_SITE.<host>.<target> Local settings for a specific host-target combination
|
||||
CONFIG_SITE.Common.<target> Local settings for a specific target, any host
|
||||
CONFIG_SITE.<host>.Common Local settings for a specific host, any target
|
||||
CONFIG_SITE.Common.RTEMS Local settings for all RTEMS targets, any host
|
||||
CONFIG_SITE.Common.vxWorksCommon Local settings for all vxWorks targets, any host
|
||||
```
|
||||
|
||||
### <span id="0_0_12">Building EPICS base (Unix and Win32)</span>
|
||||
### Building EPICS base
|
||||
|
||||
#### Unpack file
|
||||
|
||||
@@ -237,7 +256,7 @@ systems.
|
||||
Files in the base/startup directory have been provided to help set
|
||||
required path and other environment variables.
|
||||
|
||||
* `EPICS_HOST_ARCH`
|
||||
* **`EPICS_HOST_ARCH`**
|
||||
Before you can build or use EPICS R3.15, the environment variable
|
||||
`EPICS_HOST_ARCH` must be defined. A perl script EpicsHostArch.pl in
|
||||
the base/startup directory has been provided to help set
|
||||
@@ -250,65 +269,66 @@ compilers on a solaris host or "-mingw" for MinGW c/c++ compilers on
|
||||
a WIN32 host). See `configure/CONFIG_SITE` for a list of supported
|
||||
`EPICS_HOST_ARCH` values.
|
||||
|
||||
* `PERLLIB`
|
||||
On WIN32, some versions of Perl require that the environment
|
||||
variable PERLLIB be set to <perl directory location>.
|
||||
* **`PATH`**
|
||||
As already mentioned, you must have the `perl` executable and you may
|
||||
need C and C++ compilers in your search path. When building base you
|
||||
must have `echo` in your search path. For Unix host builds you will
|
||||
also need `cp`, `rm`, `mv`, and `mkdir` in your search path. Some Unix
|
||||
systems may also need `ar` and `ranlib`, and the C/C++ compilers may
|
||||
require `as` and `ld` in your path. On Solaris systems you need
|
||||
`uname` in your path.
|
||||
|
||||
* `PATH`
|
||||
As already mentioned, you must have the perl executable and you may
|
||||
need C and C++ compilers in your search path. For building base you
|
||||
also must have echo in your search path. For Unix host builds you
|
||||
also need ln, cpp, cp, rm, mv, and mkdir in your search path and
|
||||
/bin/chmod must exist. On some Unix systems you may also need ar and
|
||||
ranlib in your path, and the C compiler may require as and ld in
|
||||
your path. On solaris systems you need uname in your path.
|
||||
* **`LD_LIBRARY_PATH`**
|
||||
R3.15 shared libraries and executables normally contain the full path
|
||||
to any libraries they require, so setting this variable is not usually
|
||||
necessary. However, if you move the EPICS installation to a new
|
||||
location after building it then in order for the shared libraries to
|
||||
be found at runtime it may need to be set, or some equivalent
|
||||
OS-specific mechanism such as `/etc/ld.so.conf` on Linux must be used.
|
||||
Shared libraries are now built by default on all Unix type hosts.
|
||||
|
||||
* `LD_LIBRARY_PATH`
|
||||
R3.15 shared libraries and executables normally contain the full
|
||||
path to any libraries they require. However, if you move the EPICS
|
||||
files or directories from their build-time location then in order
|
||||
for the shared libraries to be found at runtime `LD_LIBRARY_PATH`
|
||||
must include the full pathname to
|
||||
`$(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH)` when invoking
|
||||
executables, or some equivalent OS-specific mechanism (such as
|
||||
/etc/ld.so.conf on Linux) must be used. Shared libraries are now
|
||||
built by default on all Unix type hosts.
|
||||
### Site-specific build configuration
|
||||
|
||||
#### Do site-specific build configuration
|
||||
#### Site configuration
|
||||
|
||||
**Site configuration**
|
||||
To configure EPICS, you may want to modify the default definitions
|
||||
in the following files:
|
||||
To configure EPICS, you may want to modify some values set in the
|
||||
following files:
|
||||
|
||||
```
|
||||
configure/CONFIG_SITE Build choices. Specify target archs.
|
||||
configure/CONFIG_SITE_ENV Environment variable defaults
|
||||
configure/RELEASE TORNADO2 full path location
|
||||
configure/CONFIG_SITE Build settings. Specify target archs.
|
||||
configure/CONFIG_SITE_ENV Environment variable defaults
|
||||
```
|
||||
|
||||
**Host configuration**
|
||||
To configure each host system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
changed to `CONFIG_SITE`.
|
||||
#### Host configuration
|
||||
|
||||
To configure each host system, you can override the default
|
||||
definitions by adding a new settings file (or editing an existing
|
||||
settings file) in the `configure/os` directory with your override
|
||||
definitions. The settings file has the same name as the definitions
|
||||
file to be overridden except with `CONFIG` in the name changed to
|
||||
`CONFIG_SITE`.
|
||||
|
||||
```
|
||||
configure/os/CONFIG.<host>.<host> Host build settings
|
||||
configure/os/CONFIG.<host>.Common Host common build settings
|
||||
configure/os/CONFIG.<host>.<host> Host self-build definitions
|
||||
configure/os/CONFIG.<host>.Common Host common build definitions
|
||||
configure/os/CONFIG_SITE.<host>.<host> Host self-build overrides
|
||||
configure/os/CONFIG_SITE.<host>.Common Host common build overrides
|
||||
```
|
||||
|
||||
**Target configuration**
|
||||
#### Target configuration
|
||||
|
||||
To configure each target system, you may override the default
|
||||
definitions by adding a new file in the configure/os directory with
|
||||
override definitions. The new file should have the same name as the
|
||||
distribution file to be overridden except with CONFIG in the name
|
||||
replaced by `CONFIG_SITE`. This step is necessary even if the host
|
||||
system is the only target system.
|
||||
definitions by adding a new settings file (or editing an existing
|
||||
settings file) in the `configure/os` directory with your override
|
||||
definitions. The settings file has the same name as the definitions
|
||||
file to be overridden except with `CONFIG` in the name changed to
|
||||
`CONFIG_SITE`.
|
||||
|
||||
```
|
||||
configure/os/CONFIG.Common.<target> Target common settings
|
||||
configure/os/CONFIG.<host>.<target> Host-target settings
|
||||
configure/os/CONFIG.Common.<target> Target common definitions
|
||||
configure/os/CONFIG.<host>.<target> Host-target definitions
|
||||
configure/os/CONFIG_SITE.Common.<target> Target common overrides
|
||||
configure/os/CONFIG_SITE.<host>.<target> Host-target overrides
|
||||
```
|
||||
|
||||
#### Build EPICS base
|
||||
@@ -318,24 +338,29 @@ by issuing the following commands in the distribution's root
|
||||
directory (base):
|
||||
|
||||
```
|
||||
gnumake clean uninstall
|
||||
gnumake
|
||||
make distclean
|
||||
make
|
||||
```
|
||||
|
||||
The command "gnumake clean uninstall" will remove all files and
|
||||
directories generated by a previous build. The command "gnumake"
|
||||
The command `make distclean` will remove all files and
|
||||
directories generated by a previous build. The command `make`
|
||||
will build and install everything for the configured host and
|
||||
targets.
|
||||
|
||||
It is recommended that you do a "gnumake clean uninstall" at the
|
||||
It is recommended that you do a `make distclean` at the
|
||||
root directory of an EPICS directory structure before each complete
|
||||
rebuild to ensure that all components will be rebuilt.
|
||||
|
||||
### <span id="0_0_13">Example application and extension</span>
|
||||
In some cases GNU Make may have been installed as `gmake` or
|
||||
`gnumake`, in which case the above commands will have to be adjusted
|
||||
to match.
|
||||
|
||||
A perl tool, makeBaseApp.pl is included in the distribution file. This
|
||||
script will create a sample application that can be built and then
|
||||
executed to try out this release of base.
|
||||
### Example application and extension
|
||||
|
||||
A perl tool `makeBaseApp.pl` and several template applications are
|
||||
included in the distribution. This script instantiates the selected
|
||||
template into an empty directory to provide an example application
|
||||
that can be built and then executed to try out this release of base.
|
||||
|
||||
Instructions for building and executing the 3.15 example application
|
||||
can be found in the section "Example Application" of Chapter 2,
|
||||
@@ -348,26 +373,30 @@ application as a host-based IOC, you will be able to quickly implement
|
||||
a complete EPICS system and be able to run channel access clients on
|
||||
the host system.
|
||||
|
||||
A perl script, makeBaseExt.pl, is included in the distribution file.
|
||||
This script will create a sample extension that can be built and
|
||||
executed. The makeBaseApp.pl and makeBaseExt.pl scripts are installed
|
||||
into the install location `bin/<hostarch>` directory during the base
|
||||
build.
|
||||
Another perl script `makeBaseExt.pl` is also included in the
|
||||
distribution file for creating an extensions tree and sample
|
||||
application that can also be built and executed. Both these scripts
|
||||
are installed into the install location `bin/<hostarch>` directory
|
||||
during the base build.
|
||||
|
||||
### <span id="0_0_14">Multiple host platforms</span>
|
||||
### Multiple host platforms
|
||||
|
||||
You can build using a single EPICS directory structure on multiple
|
||||
host systems and for multiple cross target systems. The intermediate
|
||||
and binary files generated by the build will be created in separate
|
||||
subdirectories and installed into the appropriate separate host/target
|
||||
install directories. EPICS executables and perl scripts are installed
|
||||
into the `$(INSTALL_LOCATION)/bin/<arch>` directories. Libraries are
|
||||
installed into $`(INSTALL_LOCATION)/lib/<arch>`. The default
|
||||
definition for `$(INSTALL_LOCATION)` is `$(TOP)` which is the root
|
||||
directory in the distribution directory structure, base. Created
|
||||
object files are stored in `O.<arch>` source subdirectories, This
|
||||
allows objects for multiple cross target architectures to be
|
||||
maintained at the same time. To build EPICS base for a specific
|
||||
install directories.
|
||||
|
||||
EPICS executables and perl scripts are installed into the
|
||||
`$(INSTALL_LOCATION)/bin/<arch>` directories. Libraries are installed
|
||||
into $`(INSTALL_LOCATION)/lib/<arch>`. The default definition for
|
||||
`$(INSTALL_LOCATION)` is `$(TOP)` which is the root directory in the
|
||||
distribution directory structure, `base`. Intermediate object files
|
||||
are stored in `O.<arch>` source subdirectories during the build
|
||||
process, to allow objects for multiple cross target architectures
|
||||
to be maintained at the same time.
|
||||
|
||||
To build EPICS base for a specific
|
||||
host/target combination you must have the proper host/target C/C++
|
||||
cross compiler and target header files and the base/configure/os
|
||||
directory must have the appropriate configure files.
|
||||
|
||||
@@ -2,16 +2,66 @@
|
||||
|
||||
This version of EPICS Base has not been released yet.
|
||||
|
||||
## Changes made on the 3.15 branch since 3.15.8
|
||||
## Changes made on the 3.15 branch since 3.15.9
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
### Support for Apple M1/M2 (arm64) Processors
|
||||
|
||||
Thanks to Jeong Han Lee this release comes with build support for Apple's new
|
||||
M1 CPUs running macOS, using the target name `darwin-aarch64`.
|
||||
|
||||
### Set thread names on Windows
|
||||
|
||||
On MS Windows, epicsThread names are made available to the OS and debugger
|
||||
using `SetThreadDescription()` if available as well as using the older
|
||||
exception mechanism.
|
||||
|
||||
### Fix timers on MS Windows for non-EPICS threads
|
||||
|
||||
The waitable timer changes in 3.15.9 broke calls to `epicsThreadSleep()` and
|
||||
similar routines that used timers (including `ca_pend_event()`) when made from
|
||||
threads that were not started using the epicsThread APIs.
|
||||
[This problem](https://github.com/epics-base/epics-base/pull/200)
|
||||
[has now been fixed](https://github.com/epics-base/epics-base/pull/201).
|
||||
|
||||
## Changes made between 3.15.8 and 3.15.9
|
||||
|
||||
### Use waitable timers on Microsoft Windows
|
||||
|
||||
The `epicsEventWaitWithTimeout()` and `epicsThreadSleep()` functions have
|
||||
been changed to use waitable timers. On Windows 10 version 1803 or higher
|
||||
they will use high resolution timers for more consistent timing.
|
||||
|
||||
See [this Google Groups thread](https://groups.google.com/a/chromium.org/g/scheduler-dev/c/0GlSPYreJeY)
|
||||
for a comparison of the performance of different timers.
|
||||
|
||||
### Build target for documentation
|
||||
|
||||
The build target `inc` now works again after a very long hiatus. It now
|
||||
generates and installs just the dbd, header and html files, without compiling
|
||||
any C/C++ code. This can be used to speed up CI jobs that only generate
|
||||
documentation.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- The error status returned by a record support's `special()` method is now propagated out of the `dbPut()` routine again (broken since 3.15.0).
|
||||
- [gh: #80](https://github.com/epics-base/epics-base/issues/80), VS-2015 and
|
||||
later have working strtod()
|
||||
- [lp: #1776141](https://bugs.launchpad.net/epics-base/+bug/1776141), Catch
|
||||
buffer overflow from long link strings
|
||||
- [lp: #1899697](https://bugs.launchpad.net/epics-base/+bug/1899697), Records
|
||||
in wrong PHAS order
|
||||
|
||||
### Change to the `junitfiles` self-test build target
|
||||
|
||||
The names of the generated junit xml test output files have been changed
|
||||
from `<testname>.xml` to `<testname>-results.xml`, to allow better
|
||||
distinction from other xml files. (I.e., for easy wildcard matching.)
|
||||
|
||||
### Fixes and code cleanups
|
||||
|
||||
Issues reported by various static code checkers.
|
||||
|
||||
## Changes made between 3.15.7 and 3.15.8
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Record Reference Documentation
|
||||
|
||||
The following documentation for the record types and menus include with Base was
|
||||
The documentation below for the record types and menus included with Base was
|
||||
converted from the old EPICS Wiki pages and updated. This list only includes the
|
||||
record types supplied with Base.
|
||||
record types supplied with Base. The first two links below are to an external
|
||||
website where these original reference chapters are now being published.
|
||||
|
||||
* [Introduction to EPICS](https://docs.epics-controls.org/en/latest/guides/EPICS_Intro.html)
|
||||
* [Process Database Concepts](https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html)
|
||||
* [Fields Common to All Record Types](dbCommonRecord.html)
|
||||
* [Fields Common to Input Record Types](dbCommonInput.html)
|
||||
* [Fields Common to Output Record Types](dbCommonOutput.html)
|
||||
@@ -33,7 +36,7 @@ record types supplied with Base.
|
||||
* [Multi-Bit Binary Output Direct Record (mbboDirect)](mbboDirectRecord.html)
|
||||
* [Multi-Bit Binary Output Record (mbbo)](mbboRecord.html)
|
||||
* [Permissive Record (permissive)](permissiveRecord.html)
|
||||
* [Printf Record (prinf)](printfRecord.html)
|
||||
* [Printf Record (printf)](printfRecord.html)
|
||||
* [Select Record (sel)](selRecord.html)
|
||||
* [Sequence Record (seq)](seqRecord.html)
|
||||
* [State Record (state)](stateRecord.html)
|
||||
@@ -51,6 +54,9 @@ record types supplied with Base.
|
||||
* [Field Type Menu](menuFtype.html)
|
||||
* [Invalid Value Output Action Menu](menuIvoa.html)
|
||||
* [Output Mode Select Menu](menuOmsl.html)
|
||||
* [Process at iocInit Menu](menuPini.html)
|
||||
* [Post Monitors Menu](menuPost.html)
|
||||
* [Priority Menu](menuPriority.html)
|
||||
* [Scan Menu](menuScan.html)
|
||||
* [Simulation Mode Menu](menuSimm.html)
|
||||
* [Yes/No Menu](menuYesNo.html)
|
||||
|
||||
@@ -50,14 +50,16 @@ bool getStringAsDouble ( const char * pString,
|
||||
ftmp = itmp;
|
||||
}
|
||||
else {
|
||||
int j = epicsScanDouble( pString, &ftmp );
|
||||
if ( j != 1 ) {
|
||||
j = sscanf ( pString,"%x", &itmp );
|
||||
if ( j == 1 ) {
|
||||
ftmp = itmp;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
int j = epicsScanDouble ( pString, &ftmp );
|
||||
if ( j != 1 ) {
|
||||
j = sscanf ( pString, "%lf", &ftmp );
|
||||
if ( j != 1 ) {
|
||||
j = sscanf ( pString, "%x", &itmp );
|
||||
if ( j == 1 ) {
|
||||
ftmp = itmp;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ public:
|
||||
private:
|
||||
clientBufMemoryManager clientBufMemMgr;
|
||||
tsFreeList < casMonitor, 1024 > casMonitorFreeList;
|
||||
tsDLList < casStrmClient > clientList;
|
||||
tsDLList < casIntfOS > intfList;
|
||||
::tsDLList < casStrmClient > clientList;
|
||||
::tsDLList < casIntfOS > intfList;
|
||||
mutable epicsMutex mutex;
|
||||
mutable epicsMutex diagnosticCountersMutex;
|
||||
caServer & adapter;
|
||||
|
||||
@@ -291,7 +291,7 @@ void casPVI::postEvent ( const casEventMask & select, const gdd & event )
|
||||
}
|
||||
|
||||
caStatus casPVI::installMonitor (
|
||||
casMonitor & mon, tsDLList < casMonitor > & monitorList )
|
||||
casMonitor & mon, ::tsDLList < casMonitor > & monitorList )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
assert ( this->nMonAttached < UINT_MAX );
|
||||
@@ -307,7 +307,7 @@ caStatus casPVI::installMonitor (
|
||||
}
|
||||
|
||||
casMonitor * casPVI::removeMonitor (
|
||||
tsDLList < casMonitor > & list, ca_uint32_t clientIdIn )
|
||||
::tsDLList < casMonitor > & list, ca_uint32_t clientIdIn )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
casMonitor * pMon = 0;
|
||||
@@ -364,8 +364,8 @@ void casPVI::installChannel ( chanIntfForPV & chan )
|
||||
}
|
||||
|
||||
void casPVI::removeChannel (
|
||||
chanIntfForPV & chan, tsDLList < casMonitor > & src,
|
||||
tsDLList < casMonitor > & dest )
|
||||
chanIntfForPV & chan, ::tsDLList < casMonitor > & src,
|
||||
::tsDLList < casMonitor > & dest )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
src.removeAll ( dest );
|
||||
@@ -379,7 +379,7 @@ void casPVI::removeChannel (
|
||||
}
|
||||
}
|
||||
|
||||
void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList )
|
||||
void casPVI::clearOutstandingReads ( ::tsDLList < casAsyncIOI > & ioList )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
@@ -399,7 +399,7 @@ void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList )
|
||||
}
|
||||
}
|
||||
|
||||
void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
|
||||
void casPVI::destroyAllIO ( ::tsDLList < casAsyncIOI > & ioList )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
while ( casAsyncIOI * pIO = ioList.get() ) {
|
||||
@@ -411,7 +411,7 @@ void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
|
||||
}
|
||||
|
||||
void casPVI::installIO (
|
||||
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
::tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
ioList.add ( io );
|
||||
@@ -420,7 +420,7 @@ void casPVI::installIO (
|
||||
}
|
||||
|
||||
void casPVI::uninstallIO (
|
||||
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
::tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
|
||||
{
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
@@ -49,21 +49,21 @@ public:
|
||||
caStatus attachToServer ( caServerI & cas );
|
||||
aitIndex nativeCount ();
|
||||
bool ioIsPending () const;
|
||||
void clearOutstandingReads ( tsDLList < class casAsyncIOI > &);
|
||||
void clearOutstandingReads ( ::tsDLList < class casAsyncIOI > &);
|
||||
void destroyAllIO (
|
||||
tsDLList < casAsyncIOI > & );
|
||||
::tsDLList < casAsyncIOI > & );
|
||||
void installIO (
|
||||
tsDLList < casAsyncIOI > &, casAsyncIOI & );
|
||||
::tsDLList < casAsyncIOI > &, casAsyncIOI & );
|
||||
void uninstallIO (
|
||||
tsDLList < casAsyncIOI > &, casAsyncIOI & );
|
||||
::tsDLList < casAsyncIOI > &, casAsyncIOI & );
|
||||
void installChannel ( chanIntfForPV & chan );
|
||||
void removeChannel (
|
||||
chanIntfForPV & chan, tsDLList < casMonitor > & src,
|
||||
tsDLList < casMonitor > & dest );
|
||||
chanIntfForPV & chan, ::tsDLList < casMonitor > & src,
|
||||
::tsDLList < casMonitor > & dest );
|
||||
caStatus installMonitor (
|
||||
casMonitor & mon, tsDLList < casMonitor > & monitorList );
|
||||
casMonitor & mon, ::tsDLList < casMonitor > & monitorList );
|
||||
casMonitor * removeMonitor (
|
||||
tsDLList < casMonitor > & list, ca_uint32_t clientIdIn );
|
||||
::tsDLList < casMonitor > & list, ca_uint32_t clientIdIn );
|
||||
void deleteSignal ();
|
||||
void postEvent ( const casEventMask & select, const gdd & event );
|
||||
caServer * getExtServer () const;
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
|
||||
private:
|
||||
mutable epicsMutex mutex;
|
||||
tsDLList < chanIntfForPV > chanList;
|
||||
::tsDLList < chanIntfForPV > chanList;
|
||||
gddEnumStringTable enumStrTbl;
|
||||
caServerI * pCAS;
|
||||
casPV * pPV;
|
||||
|
||||
@@ -19,7 +19,10 @@ BPT_DBD += bptTypeJdegC.dbd
|
||||
BPT_DBD += bptTypeJdegF.dbd
|
||||
BPT_DBD += bptTypeKdegC.dbd
|
||||
BPT_DBD += bptTypeKdegF.dbd
|
||||
|
||||
ifneq (inc,$(strip $(MAKECMDGOALS)))
|
||||
DBD += $(BPT_DBD)
|
||||
endif
|
||||
|
||||
PROD_HOST += makeBpt
|
||||
|
||||
|
||||
@@ -1290,7 +1290,8 @@ long dbPut(DBADDR *paddr, short dbrType,
|
||||
/* Always do special processing if needed */
|
||||
if (special) {
|
||||
long status2 = dbPutSpecial(paddr, 1);
|
||||
if (status2) goto done;
|
||||
if (status2)
|
||||
status = status2;
|
||||
}
|
||||
if (status) goto done;
|
||||
|
||||
|
||||
@@ -992,13 +992,10 @@ static void addToList(struct dbCommon *precord, scan_list *psl)
|
||||
pse->pscan_list = psl;
|
||||
ptemp = (scan_element *)ellLast(&psl->list);
|
||||
while (ptemp) {
|
||||
if (ptemp->precord->phas <= precord->phas) {
|
||||
ellInsert(&psl->list, &ptemp->node, &pse->node);
|
||||
break;
|
||||
}
|
||||
if (ptemp->precord->phas <= precord->phas) break;
|
||||
ptemp = (scan_element *)ellPrevious(&ptemp->node);
|
||||
}
|
||||
if (ptemp == NULL) ellAdd(&psl->list, (void *)pse);
|
||||
ellInsert(&psl->list, (ptemp ? &ptemp->node : NULL), &pse->node);
|
||||
psl->modified = TRUE;
|
||||
epicsMutexUnlock(psl->lock);
|
||||
}
|
||||
@@ -1024,7 +1021,7 @@ static void deleteFromList(struct dbCommon *precord, scan_list *psl)
|
||||
return;
|
||||
}
|
||||
pse->pscan_list = NULL;
|
||||
ellDelete(&psl->list, (void *)pse);
|
||||
ellDelete(&psl->list, &pse->node);
|
||||
psl->modified = TRUE;
|
||||
epicsMutexUnlock(psl->lock);
|
||||
}
|
||||
|
||||
@@ -41,12 +41,13 @@
|
||||
#include "special.h"
|
||||
|
||||
#define MAXLINE 80
|
||||
#define MAXMESS 128
|
||||
struct msgBuff { /* line output structure */
|
||||
char out_buff[MAXLINE + 1];
|
||||
char *pNext;
|
||||
char *pLast;
|
||||
char *pNexTab;
|
||||
char message[128];
|
||||
char message[MAXMESS];
|
||||
};
|
||||
typedef struct msgBuff TAB_BUFFER;
|
||||
|
||||
@@ -1205,7 +1206,7 @@ static int dbpr_report(
|
||||
sprintf(pmsg,"%s: Illegal Link Type", pfield_name);
|
||||
}
|
||||
else {
|
||||
sprintf(pmsg,"%s:%s %s", pfield_name,
|
||||
epicsSnprintf(pmsg, MAXMESS, "%s:%s %s", pfield_name,
|
||||
pamaplinkType[ind].strvalue,dbGetString(pdbentry));
|
||||
}
|
||||
dbpr_msgOut(pMsgBuff, tab_size);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
=head1 Menu menuIvoa
|
||||
|
||||
This menu specifies the possibile actions to take when the INVALID alarm is
|
||||
This menu specifies the possible actions to take when the INVALID alarm is
|
||||
triggered. See individual record types for more information.
|
||||
|
||||
=menu menuIvoa
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
menu(menuPini) {
|
||||
choice(menuPiniNO,"NO")
|
||||
choice(menuPiniYES,"YES")
|
||||
choice(menuPiniRUN,"RUN")
|
||||
choice(menuPiniRUNNING,"RUNNING")
|
||||
choice(menuPiniPAUSE,"PAUSE")
|
||||
choice(menuPiniPAUSED,"PAUSED")
|
||||
}
|
||||
66
src/ioc/db/menuPini.dbd.pod
Normal file
66
src/ioc/db/menuPini.dbd.pod
Normal file
@@ -0,0 +1,66 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuPini
|
||||
|
||||
This menu defines the choices for the C<PINI> field, which controls whether
|
||||
and when each record should be processed during initialization or pausing
|
||||
of the IOC. Choices other than C<NO> cause record processing at the
|
||||
following initHook transitions:
|
||||
|
||||
=over 4
|
||||
|
||||
=item YES
|
||||
|
||||
C<initHookAfterScanInit> E<mdash> All records and links have been
|
||||
initialized but the scan threads and CA server are not running yet, nor
|
||||
have CA links been connected up. The initHook C<initHookAfterInitialProcess>
|
||||
immediately follows this procssing.
|
||||
|
||||
=item RUN
|
||||
|
||||
C<initHookAtIocRun> E<mdash> The C<iocRun()> routine has just been called,
|
||||
although not necessarily for the first time.
|
||||
|
||||
=item RUNNING
|
||||
|
||||
C<initHookAfterIocRunning> E<mdash> All remaining initializations have
|
||||
taken place, C<interruptAccept> is enabled, the scan threads and CA server
|
||||
are running and the IOC is processing records. CA links might not have
|
||||
finished connecting though, and sequence programs won't usually have been
|
||||
started yet.
|
||||
|
||||
=item PAUSE
|
||||
|
||||
C<initHookAtIocPause> E<mdash> The C<iocPause()> routine has just been
|
||||
called and the IOC is about to suspend operations.
|
||||
|
||||
=item PAUSED
|
||||
|
||||
C<initHookAfterIocPaused> E<mdash> The CA server, CA link operations and
|
||||
the scan threads have been paused and C<interruptAccept> disabled.
|
||||
|
||||
=back
|
||||
|
||||
Note that the order in which records that have the same C<PINI> value get
|
||||
processed can be controlled by setting their C<PHAS> field, which is honored
|
||||
for C<PINI> processing as well as for regular scanning.
|
||||
|
||||
=menu menuPini
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuPini) {
|
||||
choice(menuPiniNO,"NO")
|
||||
choice(menuPiniYES,"YES")
|
||||
choice(menuPiniRUN,"RUN")
|
||||
choice(menuPiniRUNNING,"RUNNING")
|
||||
choice(menuPiniPAUSE,"PAUSE")
|
||||
choice(menuPiniPAUSED,"PAUSED")
|
||||
}
|
||||
@@ -5,6 +5,16 @@
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuPost
|
||||
|
||||
This menu is used by the long string record types to specify whether they
|
||||
should generate a monitor event only when their string value changes, or
|
||||
every time it gets written to even if the value is the same.
|
||||
|
||||
=menu menuPost
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuPost) {
|
||||
choice(menuPost_OnChange, "On Change")
|
||||
choice(menuPost_Always, "Always")
|
||||
@@ -7,6 +7,20 @@
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuPriority
|
||||
|
||||
This menu is used for the C<PRIO> field of all record types. It controls
|
||||
the relative priority of records scheduled with C<SCAN=Event> or
|
||||
C<SCAN=I/O Intr>, and also of records that use asynchronous completion.
|
||||
|
||||
=menu menuPriority
|
||||
|
||||
The number of priorities is set in various other places in the code too,
|
||||
so adding new entries to this menu will probably break the IOC build.
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuPriority) {
|
||||
choice(menuPriorityLOW,"LOW")
|
||||
choice(menuPriorityMEDIUM,"MEDIUM")
|
||||
@@ -300,11 +300,11 @@ static void makeSubstitutions(inputData * const inputPvt,
|
||||
char *pstart;
|
||||
char *pend;
|
||||
int cmdind=-1;
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NELEMENTS(cmdNames); i++) {
|
||||
if (strstr(command, cmdNames[i])) {
|
||||
cmdind = i;
|
||||
cmdind = (int)i;
|
||||
}
|
||||
}
|
||||
if (cmdind < 0) goto endcmd;
|
||||
|
||||
@@ -171,7 +171,12 @@ int testDone(void) {
|
||||
|
||||
epicsMutexMustLock(testLock);
|
||||
if (perlHarness) {
|
||||
if (!planned) printf("1..%d\n", tested);
|
||||
if (!planned)
|
||||
printf("1..%d\n", tested);
|
||||
else if (tested != planned)
|
||||
status = 2;
|
||||
if (failed)
|
||||
status |= 1;
|
||||
} else {
|
||||
if (planned && tested > planned) {
|
||||
printf("\nRan %d tests but only planned for %d!\n", tested, planned);
|
||||
@@ -186,7 +191,7 @@ int testDone(void) {
|
||||
if (bonus) testResult("Todo Passes", bonus);
|
||||
if (failed) {
|
||||
testResult("Failed", failed);
|
||||
status = 1;
|
||||
status |= 1;
|
||||
}
|
||||
if (skipped) testResult("Skipped", skipped);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "shareLib.h"
|
||||
#include "epicsEvent.h"
|
||||
|
||||
#include "osdThreadPvt.h"
|
||||
|
||||
typedef struct epicsEventOSD {
|
||||
HANDLE handle;
|
||||
} epicsEventOSD;
|
||||
@@ -90,27 +92,47 @@ epicsShareFunc epicsEventStatus epicsEventWait ( epicsEventId pSem )
|
||||
epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout (
|
||||
epicsEventId pSem, double timeOut )
|
||||
{
|
||||
static const unsigned mSecPerSec = 1000;
|
||||
/* waitable timers use 100 nanosecond intervals, like FILETIME */
|
||||
static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */
|
||||
static const unsigned mSecPerSec = 1000u; /* milliseconds per second */
|
||||
HANDLE handles[2];
|
||||
DWORD status;
|
||||
DWORD tmo;
|
||||
LARGE_INTEGER tmo;
|
||||
HANDLE timer;
|
||||
LONGLONG nIvals; /* number of intervals */
|
||||
|
||||
if ( timeOut <= 0.0 ) {
|
||||
tmo = 0u;
|
||||
tmo.QuadPart = 0u;
|
||||
}
|
||||
else if ( timeOut >= INFINITE / mSecPerSec ) {
|
||||
tmo = INFINITE - 1;
|
||||
else if ( timeOut >= INFINITE / mSecPerSec ) {
|
||||
/* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds,
|
||||
to be compatible with previous WaitForSingleObject() implementation */
|
||||
nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec);
|
||||
tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */
|
||||
}
|
||||
else {
|
||||
tmo = ( DWORD ) ( ( timeOut * mSecPerSec ) + 0.5 );
|
||||
if ( tmo == 0 ) {
|
||||
tmo = 1;
|
||||
}
|
||||
nIvals = (LONGLONG)(timeOut * ivalPerSec + 0.999999);
|
||||
tmo.QuadPart = -nIvals;
|
||||
}
|
||||
|
||||
if (tmo.QuadPart < 0) {
|
||||
timer = osdThreadGetTimer();
|
||||
if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) {
|
||||
return epicsEventError;
|
||||
}
|
||||
handles[0] = pSem->handle;
|
||||
handles[1] = timer;
|
||||
status = WaitForMultipleObjects (2, handles, FALSE, INFINITE);
|
||||
}
|
||||
else {
|
||||
status = WaitForSingleObject(pSem->handle, 0);
|
||||
}
|
||||
status = WaitForSingleObject ( pSem->handle, tmo );
|
||||
if ( status == WAIT_OBJECT_0 ) {
|
||||
return epicsEventOK;
|
||||
}
|
||||
else if ( status == WAIT_TIMEOUT ) {
|
||||
else if ( status == WAIT_OBJECT_0 + 1 || status == WAIT_TIMEOUT ) {
|
||||
/* WaitForMultipleObjects will trigger WAIT_OBJECT_0 + 1,
|
||||
WaitForSingleObject will trigger WAIT_TIMEOUT */
|
||||
return epicsEventWaitTimeout;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* epicsStrtod() for systems with broken strtod() routine
|
||||
*/
|
||||
epicsShareFunc double epicsStrtod(const char *str, char **endp);
|
||||
|
||||
/*
|
||||
* Microsoft apparently added strto[u]ll() in VS2013
|
||||
@@ -28,6 +24,19 @@ epicsShareFunc double epicsStrtod(const char *str, char **endp);
|
||||
# define strtoull _strtoui64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* strtod works in MSVC 1900 and mingw, use
|
||||
* the OS version in those and our own otherwise
|
||||
*/
|
||||
#if (_MSC_VER < 1900) && !defined(_MINGW)
|
||||
/*
|
||||
* epicsStrtod() for systems with broken strtod() routine
|
||||
*/
|
||||
epicsShareFunc double epicsStrtod(const char *str, char **endp);
|
||||
#else
|
||||
# define epicsStrtod strtod
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
#define VC_EXTRALEAN
|
||||
#define STRICT
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x400 /* No support for W95 */
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <process.h> /* for _endthread() etc */
|
||||
|
||||
@@ -33,6 +30,8 @@
|
||||
#include "ellLib.h"
|
||||
#include "epicsExit.h"
|
||||
|
||||
#include "osdThreadPvt.h"
|
||||
|
||||
epicsShareFunc void osdThreadHooksRun(epicsThreadId id);
|
||||
|
||||
void setThreadName ( DWORD dwThreadID, LPCSTR szThreadName );
|
||||
@@ -53,6 +52,7 @@ typedef struct epicsThreadOSD {
|
||||
DWORD id;
|
||||
unsigned epicsPriority;
|
||||
char isSuspended;
|
||||
HANDLE timer; /* waitable timer */
|
||||
} win32ThreadParam;
|
||||
|
||||
typedef struct epicsThreadPrivateOSD {
|
||||
@@ -229,6 +229,19 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void )
|
||||
return pWin32ThreadGlobal;
|
||||
}
|
||||
|
||||
static void epicsParmCleanupDataWIN32 ( win32ThreadParam * pParm )
|
||||
{
|
||||
if ( pParm ) {
|
||||
if ( pParm->handle ) {
|
||||
CloseHandle ( pParm->handle );
|
||||
}
|
||||
if ( pParm->timer ) {
|
||||
CloseHandle ( pParm->timer );
|
||||
}
|
||||
free ( pParm );
|
||||
}
|
||||
}
|
||||
|
||||
static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm )
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
@@ -243,8 +256,8 @@ static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm )
|
||||
ellDelete ( & pGbl->threadList, & pParm->node );
|
||||
LeaveCriticalSection ( & pGbl->mutex );
|
||||
|
||||
CloseHandle ( pParm->handle );
|
||||
free ( pParm );
|
||||
epicsParmCleanupDataWIN32 ( pParm );
|
||||
|
||||
TlsSetValue ( pGbl->tlsIndexThreadLibraryEPICS, 0 );
|
||||
}
|
||||
}
|
||||
@@ -464,21 +477,6 @@ epicsShareFunc unsigned int epicsShareAPI
|
||||
return stackSizeTable[stackSizeClass];
|
||||
}
|
||||
|
||||
void epicsThreadCleanupWIN32 ()
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm;
|
||||
|
||||
if ( ! pGbl ) {
|
||||
fprintf ( stderr, "epicsThreadCleanupWIN32: unable to find ctx\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
pParm = ( win32ThreadParam * )
|
||||
TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
|
||||
epicsParmCleanupWIN32 ( pParm );
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsWin32ThreadEntry()
|
||||
*/
|
||||
@@ -526,6 +524,16 @@ static win32ThreadParam * epicsThreadParmCreate ( const char *pName )
|
||||
pParmWIN32->pName = (char *) ( pParmWIN32 + 1 );
|
||||
strcpy ( pParmWIN32->pName, pName );
|
||||
pParmWIN32->isSuspended = 0;
|
||||
#ifdef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||
pParmWIN32->timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||
#endif
|
||||
if (pParmWIN32->timer == NULL) {
|
||||
pParmWIN32->timer = CreateWaitableTimer(NULL, 0, NULL);
|
||||
}
|
||||
if (pParmWIN32->timer == NULL) {
|
||||
free(pParmWIN32);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return pParmWIN32;
|
||||
}
|
||||
@@ -608,7 +616,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
|
||||
CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||
& threadId );
|
||||
if ( pParmWIN32->handle == 0 ) {
|
||||
free ( pParmWIN32 );
|
||||
epicsParmCleanupDataWIN32 ( pParmWIN32 );
|
||||
return NULL;
|
||||
}
|
||||
/* weird win32 interface threadId parameter inconsistency */
|
||||
@@ -618,8 +626,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
|
||||
osdPriority = epicsThreadGetOsdPriorityValue (priority);
|
||||
bstat = SetThreadPriority ( pParmWIN32->handle, osdPriority );
|
||||
if (!bstat) {
|
||||
CloseHandle ( pParmWIN32->handle );
|
||||
free ( pParmWIN32 );
|
||||
epicsParmCleanupDataWIN32 ( pParmWIN32 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -632,8 +639,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
|
||||
EnterCriticalSection ( & pGbl->mutex );
|
||||
ellDelete ( & pGbl->threadList, & pParmWIN32->node );
|
||||
LeaveCriticalSection ( & pGbl->mutex );
|
||||
CloseHandle ( pParmWIN32->handle );
|
||||
free ( pParmWIN32 );
|
||||
epicsParmCleanupDataWIN32 ( pParmWIN32 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -641,21 +647,34 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate (const char *pName,
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsThreadSuspendSelf ()
|
||||
* getMyWin32ThreadParam ()
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf ()
|
||||
static void* getMyWin32ThreadParam ( win32ThreadGlobal * pGbl )
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm;
|
||||
DWORD stat;
|
||||
|
||||
assert ( pGbl );
|
||||
if ( ! pGbl ) {
|
||||
pGbl = fetchWin32ThreadGlobal ();
|
||||
assert ( pGbl );
|
||||
}
|
||||
|
||||
pParm = ( win32ThreadParam * )
|
||||
TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
|
||||
if ( ! pParm ) {
|
||||
pParm = epicsThreadImplicitCreate ();
|
||||
}
|
||||
return pParm;
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsThreadSuspendSelf ()
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf ()
|
||||
{
|
||||
DWORD stat;
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm = getMyWin32ThreadParam ( pGbl );
|
||||
|
||||
if ( pParm ) {
|
||||
EnterCriticalSection ( & pGbl->mutex );
|
||||
pParm->isSuspended = 1;
|
||||
@@ -700,16 +719,8 @@ epicsShareFunc unsigned epicsShareAPI epicsThreadGetPriority (epicsThreadId id)
|
||||
*/
|
||||
epicsShareFunc unsigned epicsShareAPI epicsThreadGetPrioritySelf ()
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm;
|
||||
win32ThreadParam * pParm = getMyWin32ThreadParam ( NULL );
|
||||
|
||||
assert ( pGbl );
|
||||
|
||||
pParm = ( win32ThreadParam * )
|
||||
TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
|
||||
if ( ! pParm ) {
|
||||
pParm = epicsThreadImplicitCreate ();
|
||||
}
|
||||
if ( pParm ) {
|
||||
return pParm->epicsPriority;
|
||||
}
|
||||
@@ -764,24 +775,59 @@ epicsShareFunc int epicsShareAPI epicsThreadIsSuspended ( epicsThreadId id )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* osdThreadGetTimer ()
|
||||
* return stored waitable timer object for thread
|
||||
*/
|
||||
HANDLE osdThreadGetTimer()
|
||||
{
|
||||
win32ThreadParam * pParm = getMyWin32ThreadParam ( NULL );
|
||||
if (pParm) {
|
||||
return pParm->timer;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* epicsThreadSleep ()
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI epicsThreadSleep ( double seconds )
|
||||
{
|
||||
static const unsigned mSecPerSec = 1000;
|
||||
DWORD milliSecDelay;
|
||||
/* waitable timers use 100 nanosecond intervals, like FILETIME */
|
||||
static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */
|
||||
static const unsigned mSecPerSec = 1000u; /* milliseconds per second */
|
||||
LARGE_INTEGER tmo;
|
||||
HANDLE timer;
|
||||
LONGLONG nIvals; /* number of intervals */
|
||||
|
||||
if ( seconds > 0.0 ) {
|
||||
seconds *= mSecPerSec;
|
||||
seconds += 0.99999999; /* 8 9s here is optimal */
|
||||
milliSecDelay = ( seconds >= INFINITE ) ?
|
||||
INFINITE - 1 : ( DWORD ) seconds;
|
||||
if ( seconds <= 0.0 ) {
|
||||
tmo.QuadPart = 0u;
|
||||
}
|
||||
else { /* seconds <= 0 or NAN */
|
||||
milliSecDelay = 0u;
|
||||
else if ( seconds >= INFINITE / mSecPerSec ) {
|
||||
/* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds,
|
||||
to be compatible with previous WaitForSingleObject() implementation */
|
||||
nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec);
|
||||
tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */
|
||||
}
|
||||
else {
|
||||
nIvals = (LONGLONG)(seconds * ivalPerSec + 0.999999);
|
||||
tmo.QuadPart = -nIvals;
|
||||
}
|
||||
|
||||
if (tmo.QuadPart == 0) {
|
||||
Sleep ( 0 );
|
||||
}
|
||||
else {
|
||||
timer = osdThreadGetTimer();
|
||||
if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) {
|
||||
fprintf ( stderr, "epicsThreadSleep: SetWaitableTimer failed %lu\n", GetLastError() );
|
||||
return;
|
||||
}
|
||||
if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) {
|
||||
fprintf ( stderr, "epicsThreadSleep: WaitForSingleObject failed %lu\n", GetLastError() );
|
||||
}
|
||||
}
|
||||
Sleep ( milliSecDelay );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -821,17 +867,8 @@ double epicsShareAPI epicsThreadSleepQuantum ()
|
||||
*/
|
||||
epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf (void)
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm;
|
||||
|
||||
assert ( pGbl );
|
||||
|
||||
pParm = ( win32ThreadParam * ) TlsGetValue (
|
||||
pGbl->tlsIndexThreadLibraryEPICS );
|
||||
if ( ! pParm ) {
|
||||
pParm = epicsThreadImplicitCreate ();
|
||||
assert ( pParm ); /* very dangerous to allow non-unique thread id into use */
|
||||
}
|
||||
win32ThreadParam * pParm = getMyWin32ThreadParam ( NULL );
|
||||
assert ( pParm ); /* very dangerous to allow non-unique thread id into use */
|
||||
return ( epicsThreadId ) pParm;
|
||||
}
|
||||
|
||||
@@ -868,19 +905,7 @@ epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId ( const char * pName
|
||||
*/
|
||||
epicsShareFunc const char * epicsShareAPI epicsThreadGetNameSelf (void)
|
||||
{
|
||||
win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal ();
|
||||
win32ThreadParam * pParm;
|
||||
|
||||
if ( ! pGbl ) {
|
||||
return "thread library not initialized";
|
||||
}
|
||||
|
||||
pParm = ( win32ThreadParam * )
|
||||
TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS );
|
||||
if ( ! pParm ) {
|
||||
pParm = epicsThreadImplicitCreate ();
|
||||
}
|
||||
|
||||
win32ThreadParam * pParm = getMyWin32ThreadParam ( NULL );
|
||||
if ( pParm ) {
|
||||
if ( pParm->pName ) {
|
||||
return pParm->pName;
|
||||
|
||||
14
src/libCom/osi/os/WIN32/osdThreadPvt.h
Normal file
14
src/libCom/osi/os/WIN32/osdThreadPvt.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef osdThreadPvth
|
||||
#define osdThreadPvth
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern HANDLE osdThreadGetTimer(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* osdThreadPvth */
|
||||
@@ -8,44 +8,86 @@
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#define VC_EXTRALEAN
|
||||
#define STRICT
|
||||
#if _WIN64
|
||||
# define _WIN32_WINNT 0x400 /* defining this drops support for W95 */
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
* this was copied directly from an example in visual c++ 7 documentation,
|
||||
* It uses visual C++ specific keywords for exception handling, but is
|
||||
* probably only useful when using the visual c++ or later debugger.
|
||||
*
|
||||
* Usage: setThreadName (-1, "MainThread");
|
||||
*/
|
||||
|
||||
|
||||
static void setThreadNameVS ( DWORD dwThreadID, LPCSTR szThreadName );
|
||||
typedef HRESULT (WINAPI* setDesc_t)(HANDLE, PCWSTR);
|
||||
|
||||
extern "C" void setThreadName ( DWORD dwThreadID, LPCSTR szThreadName )
|
||||
{
|
||||
static HMODULE hKernel = LoadLibrary("KernelBase.dll");
|
||||
static setDesc_t pSetDesc = (hKernel != NULL ?
|
||||
(setDesc_t)GetProcAddress(hKernel, "SetThreadDescription") : NULL);
|
||||
if (szThreadName == NULL || *szThreadName == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (pSetDesc != NULL)
|
||||
{
|
||||
#ifdef THREAD_SET_LIMITED_INFORMATION
|
||||
DWORD thread_access = THREAD_SET_LIMITED_INFORMATION;
|
||||
#else
|
||||
DWORD thread_access = THREAD_SET_INFORMATION;
|
||||
#endif /* ifdef THREAD_SET_LIMITED_INFORMATION */
|
||||
HANDLE hThread = OpenThread(thread_access, FALSE, dwThreadID);
|
||||
if (hThread != NULL)
|
||||
{
|
||||
const std::string s(szThreadName);
|
||||
const std::wstring ws(s.begin(), s.end());
|
||||
HRESULT hr = (*pSetDesc)(hThread, ws.c_str());
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
}
|
||||
// if SetThreadDescription() was available and we have a recent
|
||||
// visual studio debugger (2017 version 15.6 or higher) attached
|
||||
// then the names will already be defined. However we don't know
|
||||
// this for sure, so also trigger the old exception mechanism.
|
||||
// See https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
|
||||
setThreadNameVS(dwThreadID, szThreadName);
|
||||
}
|
||||
|
||||
static void setThreadNameVS( DWORD dwThreadID, LPCSTR szThreadName )
|
||||
{
|
||||
#if _MSC_VER >= 1300 && defined ( _DEBUG )
|
||||
// This was copied directly from an MSDN example
|
||||
// It sets the thread name by throwing a special exception that is caught by Visual Sudio
|
||||
// It requires the debugger to be already attached to the process
|
||||
// when the exception is thrown for the name to be registered
|
||||
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
LPCSTR szName; // pointer to name (in user addr space)
|
||||
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||
DWORD dwFlags; // reserved for future use, must be zero
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6320 6322)
|
||||
__try
|
||||
{
|
||||
RaiseException( 0x406D1388, 0,
|
||||
sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info );
|
||||
RaiseException(MS_VC_EXCEPTION, 0,
|
||||
sizeof(info) / sizeof(ULONG_PTR),
|
||||
(ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ bswap32(epicsUInt32 value)
|
||||
#elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
|
||||
|
||||
/* Get hton[sl] declarations: */
|
||||
#include <osdSock.h>
|
||||
#include <osiSock.h>
|
||||
|
||||
/** @ingroup mmio
|
||||
*@{
|
||||
|
||||
@@ -301,10 +301,10 @@ int status;
|
||||
arg.ok = 0;
|
||||
|
||||
status = pthread_create(&id, 0, find_pri_range, &arg);
|
||||
checkStatusQuit(status, "pthread_create","epicsThreadInit");
|
||||
checkStatusOnceQuit(status, "pthread_create","epicsThreadInit");
|
||||
|
||||
status = pthread_join(id, &dummy);
|
||||
checkStatusQuit(status, "pthread_join","epicsThreadInit");
|
||||
checkStatusOnceQuit(status, "pthread_join","epicsThreadInit");
|
||||
|
||||
a_p->minPriority = arg.min_pri;
|
||||
a_p->maxPriority = arg.max_pri;
|
||||
@@ -320,9 +320,9 @@ static void once(void)
|
||||
|
||||
pthread_key_create(&getpthreadInfo,0);
|
||||
status = pthread_mutex_init(&onceLock,0);
|
||||
checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
checkStatusOnceQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
status = pthread_mutex_init(&listLock,0);
|
||||
checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
checkStatusOnceQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
pcommonAttr = calloc(1,sizeof(commonAttr));
|
||||
if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","epicsThreadInit");
|
||||
status = pthread_attr_init(&pcommonAttr->attr);
|
||||
|
||||
@@ -108,13 +108,14 @@ inline double delayVerify::delay () const
|
||||
|
||||
double delayVerify::checkError () const
|
||||
{
|
||||
const double messageThresh = 5.0; // percent
|
||||
double actualDelay = this->expireStamp - this->beginStamp;
|
||||
double measuredError = actualDelay - this->expectedDelay;
|
||||
double percentError = 100.0 * fabs ( measuredError ) / this->expectedDelay;
|
||||
testOk ( percentError < messageThresh, "%f < %f, delay = %f s, error = %f s (%.1f %%)",
|
||||
percentError, messageThresh,
|
||||
this->expectedDelay, measuredError, percentError );
|
||||
const double minError = 0.25;
|
||||
double measuredDelay = this->expireStamp - this->beginStamp;
|
||||
double measuredError = measuredDelay - this->expectedDelay;
|
||||
double absoluteError = fabs(measuredError);
|
||||
double percentError = 100.0 * measuredError / this->expectedDelay;
|
||||
testOk(absoluteError < minError,
|
||||
"Delay %.3f s, error = %+.6f ms (%+.3f %%)",
|
||||
this->expectedDelay, measuredError * 1000, percentError);
|
||||
return measuredError;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
#include "yajl_encode.h"
|
||||
#include "yajl_bytestack.h"
|
||||
|
||||
#include <epicsStdlib.h>
|
||||
|
||||
unsigned char *
|
||||
yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
|
||||
unsigned int jsonTextLen, int verbose)
|
||||
@@ -67,14 +69,14 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int memneeded = 0;
|
||||
size_t memneeded = 0;
|
||||
memneeded += strlen(errorType);
|
||||
memneeded += strlen(" error");
|
||||
if (errorText != NULL) {
|
||||
memneeded += strlen(": ");
|
||||
memneeded += strlen(errorText);
|
||||
}
|
||||
str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
|
||||
str = (unsigned char *) YA_MALLOC(&(hand->alloc), (unsigned int)(memneeded + 2));
|
||||
str[0] = 0;
|
||||
strcat((char *) str, errorType);
|
||||
strcat((char *) str, " error");
|
||||
@@ -263,7 +265,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
|
||||
yajl_buf_clear(hand->decodeBuf);
|
||||
yajl_buf_append(hand->decodeBuf, buf, bufLen);
|
||||
buf = yajl_buf_data(hand->decodeBuf);
|
||||
d = strtod((char *) buf, NULL);
|
||||
d = epicsStrtod((char *) buf, NULL);
|
||||
if ((d == HUGE_VAL || d == -HUGE_VAL) &&
|
||||
errno == ERANGE)
|
||||
{
|
||||
|
||||
@@ -99,22 +99,23 @@ SELM is a menu, with three choices:
|
||||
|
||||
=menu dfanoutSELM
|
||||
|
||||
If SELM=="All", then all output links are used, and the values of
|
||||
If SELM is C<All>, then all output links are used, and the values of
|
||||
SELL and SELN are ignored.
|
||||
|
||||
If SELM=="Specified", then the value of SELN is used to specify a single
|
||||
If SELM is C<Specified>, then the value of SELN is used to specify a single
|
||||
link which will be used. If SELN==0, then no link will be used; if SELN==1,
|
||||
then OUTA will be used, and so on.
|
||||
|
||||
SELN can either have its value set directly, or have its values retrieved
|
||||
from another EPICS PV. If SELL is a valid PV link, then SELN will be set to
|
||||
the values of the linked PV.
|
||||
SELN can either have its value set directly, or have it retrieved from
|
||||
another EPICS PV. If SELL is a valid PV link, then SELN will be read from
|
||||
the linked PV.
|
||||
|
||||
If SELM=="Mask", then SELN will be treated as a bit mask. If bit one of
|
||||
SELN is set, then OUTA will be used, if bit two is set, OUTB will be used.
|
||||
Thus if SELN==5, OUTC and OUTA will be used.
|
||||
If SELM is C<Mask>, then SELN will be treated as a bit mask. If bit zero
|
||||
(the LSB) of SELN is set, then OUTA will be written to; if bit one is set,
|
||||
OUTB will be written to, and so on. Thus when SELN==5, both OUTC and OUTA
|
||||
will be written to.
|
||||
|
||||
=fields OUTA, OUTB, OUTC, OUTD, OUTE, OUTF, OUTG, OUTH
|
||||
=fields SELL, SELM, SELN, OUTA, OUTB, OUTC, OUTD, OUTE, OUTF, OUTG, OUTH
|
||||
|
||||
=head3 Operator Display Parameters
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# SPDX-License-Identifier: EPICS
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
@@ -34,6 +35,8 @@ sub HostArch {
|
||||
return 'linux-x86_64' if m/^x86_64-linux/;
|
||||
return 'linux-x86' if m/^i[3-6]86-linux/;
|
||||
return 'linux-arm' if m/^arm-linux/;
|
||||
return 'linux-aarch64' if m/^aarch64-linux/;
|
||||
return 'linux-ppc64' if m/^powerpc64-linux/;
|
||||
return 'windows-x64' if m/^MSWin32-x64/;
|
||||
return 'win32-x86' if m/^MSWin32-x86/;
|
||||
return "cygwin-x86_64" if m/^x86_64-cygwin/;
|
||||
@@ -44,8 +47,8 @@ sub HostArch {
|
||||
my ($kernel, $hostname, $release, $version, $cpu) = uname;
|
||||
if (m/^darwin/) {
|
||||
for ($cpu) {
|
||||
return 'darwin-x86' if m/^(i386|x86_64)/;
|
||||
return 'darwin-ppc' if m/Power Macintosh/;
|
||||
return 'darwin-x86' if m/^x86_64/;
|
||||
return 'darwin-aarch64' if m/^arm64/;
|
||||
}
|
||||
die "$0: macOS CPU type '$cpu' not recognized\n";
|
||||
}
|
||||
|
||||
@@ -86,6 +86,8 @@ CLEANS += epics-base-$(T_A).pc@
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
inc: $(INSTALLS_PERL_MODULES) $(INSTALL_SCRIPTS)
|
||||
|
||||
epics-base-$(T_A).pc@: ../epics-base-arch.pc@
|
||||
@$(RM) $@
|
||||
@$(CP) $< $@
|
||||
|
||||
@@ -36,8 +36,10 @@ use Cwd 'abs_path';
|
||||
|
||||
if (\$^O eq 'MSWin32') {
|
||||
# Use system on Windows, exec doesn't work the same there and
|
||||
# GNUmake thinks the test has finished as soon as Perl exits.
|
||||
system('./$exe') == 0 or die "Can't run $exe: \$!\\n";
|
||||
# GNUmake thinks the test has finished too soon.
|
||||
my \$status = system('./$exe');
|
||||
die "Can't run $exe: \$!\\n" if \$status == -1;
|
||||
exit \$status >> 8;
|
||||
}
|
||||
else {
|
||||
exec './$exe' or die "Can't run $exe: \$!\\n";
|
||||
|
||||
@@ -4,30 +4,50 @@
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# This file may appear trivial, but it exists to let the build system
|
||||
# fail the 'make test-results' target with a nice output including a
|
||||
# summary of the directories where test failures were reported.
|
||||
# Test results are collected from the .tap files fed to epicsProve.pl
|
||||
# which returns with an exit status of 0 (success) if all tests passed
|
||||
# or 1 (failure) if any of the .tap files contained failed tests.
|
||||
# When epicsProve.pl indicates a failure, the directory that it was
|
||||
# running in is appended to the file $(TOP)/.tests-failed which this
|
||||
# program reads in after all the test directories have been visited.
|
||||
# This file lets the build system fail a top-level 'make test-results'
|
||||
# target with output showing the directories where test failures were
|
||||
# reported and the test programs that failed there.
|
||||
#
|
||||
# The exit status of this program is 1 (failure) if any tests failed,
|
||||
# otherwise 0 (success).
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
die "Usage: testFailures.pl .tests-failed\n"
|
||||
unless @ARGV == 1;
|
||||
use File::Basename;
|
||||
|
||||
open FAILURES, '<', shift or
|
||||
die "Usage: testFailures.pl /path/to/top/.tests-failed.log .taps-failed.log\n"
|
||||
unless @ARGV == 2;
|
||||
|
||||
my ($dirlog, $faillog) = @ARGV;
|
||||
my $top = dirname($dirlog);
|
||||
|
||||
# No file means success.
|
||||
open(my $logfile, '<', $dirlog) or
|
||||
exit 0;
|
||||
my @failures = <FAILURES>;
|
||||
close FAILURES;
|
||||
my @faildirs = dedup(<$logfile>);
|
||||
close $logfile;
|
||||
chomp @faildirs;
|
||||
|
||||
print "\nTest failures were reported in:\n",
|
||||
(map {" $_"} @failures), "\n";
|
||||
# Empty file also means success.
|
||||
exit 0 unless grep {$_} @faildirs;
|
||||
|
||||
print "\nTests failed in:\n";
|
||||
for my $dir (@faildirs) {
|
||||
my $reldir = $dir;
|
||||
$reldir =~ s($top/)();
|
||||
print " $reldir\n";
|
||||
open(my $taplog, '<', "$dir/$faillog") or next;
|
||||
my @taps = dedup(<$taplog>);
|
||||
close $taplog;
|
||||
chomp @taps;
|
||||
print '', (map {" $_\n"} @taps), "\n";
|
||||
}
|
||||
|
||||
exit 1;
|
||||
|
||||
sub dedup {
|
||||
my %dedup;
|
||||
$dedup{$_}++ for @_;
|
||||
return sort keys %dedup;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user