diff --git a/.ci-local/libevent.py b/.ci-local/libevent.py index 946216f..9bfdcd0 100644 --- a/.ci-local/libevent.py +++ b/.ci-local/libevent.py @@ -71,3 +71,10 @@ elif os.environ.get('WINE')=='32': F.write('\nCROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw\n') check_call('make -C bundle libevent.win32-x86-mingw', shell=True, env=env) + +elif os.environ.get('RTEMS_TARGET'): + print('Enable RTEMS') + with open('configure/CONFIG_SITE.local', 'a') as F: + F.write('\nCROSS_COMPILER_TARGET_ARCHS+=%s\n'%os.environ['RTEMS_TARGET']) + + check_call('make -C bundle libevent.'+os.environ['RTEMS_TARGET'], shell=True, env=env) diff --git a/.github/workflows/ci-scripts-build.yml b/.github/workflows/ci-scripts-build.yml index 317edd0..098526d 100644 --- a/.github/workflows/ci-scripts-build.yml +++ b/.github/workflows/ci-scripts-build.yml @@ -28,7 +28,10 @@ jobs: BCFG: ${{ matrix.configuration }} BASE: ${{ matrix.base }} WINE: ${{ matrix.wine }} + RTEMS: ${{ matrix.rtems }} + RTEMS_TARGET: ${{ matrix.rtems_target }} LIBEVENT_TAG: ${{ matrix.libevent }} + TEST: ${{ matrix.test }} EXTRA: ${{ matrix.extra }} VV: "1" strategy: @@ -56,6 +59,15 @@ jobs: base: "7.0" wine: "64" + - name: RTEMS5 + os: ubuntu-20.04 + cmp: gcc + configuration: default + base: "7.0" + rtems: "5" + rtems_target: RTEMS-pc686-qemu + test: NO + - name: Native Linux with clang os: ubuntu-20.04 cmp: clang diff --git a/bundle/Makefile b/bundle/Makefile index c85e846..e739098 100644 --- a/bundle/Makefile +++ b/bundle/Makefile @@ -60,7 +60,13 @@ ifneq (,$(filter win%,$(EPICS_HOST_ARCH))) CMAKEFLAGS += -G "MinGW Makefiles" -DCMAKE_C_COMPILER="$(CC)" endif +ifneq (,$(filter RTEMS%,$(T_A))) +CMAKE_TOOLCHAIN_$(T_A) = $(T_A).cmake +CMAKE_TOOLCHAIN_D_$(T_A) = $(CMAKE_TOOLCHAIN_$(T_A)) +endif + # toolchain file when cross compiling +CMAKE_TOOLCHAIN_D ?= $(CMAKE_TOOLCHAIN_D_$(T_A)) CMAKE_TOOLCHAIN ?= $(CMAKE_TOOLCHAIN_$(T_A)) CMAKEFLAGS += $(if $(CMAKE_TOOLCHAIN),-DCMAKE_TOOLCHAIN_FILE=$(CMAKE_TOOLCHAIN)) @@ -107,7 +113,7 @@ else # T_A ifeq (YES,$(LIBEVENT_USE_CMAKE)) # libevent >= 2.1 prefer CMake -libevent.%: +libevent.%: $(CMAKE_TOOLCHAIN_D) $(CMAKE) $(CMAKEFLAGS) ../libevent $(CMAKE) -E env --unset=MAKEFLAGS --unset=CC $(CMAKE) --build . $(CBUILDFLAGS) --target install ifneq (,$(filter %mingw,$(T_A))) @@ -122,6 +128,22 @@ ifeq (NO,$(SHARED_LIBRARIES)) endif endif +EXPANDFLAGS = $(foreach var,$(EXPANDVARS),-D$(var)="$($(var))") + +ifneq (,$(filter RTEMS%,$(T_A))) +# cf. cmake/RTEMS.cmake@ +EXPANDVARS+=RTEMS_CPU +EXPANDVARS+=RTEMS_BSP +EXPANDVARS+=RTEMS_VERSION +EXPANDVARS+=RTEMS_BASE +EXPANDVARS+=CPU_CFLAGS + +$(T_A).cmake: ../cmake/RTEMS.cmake@ + $(PERL) $(TOOLS)/expandVars.pl -a $(T_A) -t $(INSTALL_LOCATION) $(EXPANDFLAGS) $< $@ +# can't use $(EXPAND_TOOL) as this def is in a RULES_ file... +endif + + else # libevent 2.0 only autotools # only host CC supported diff --git a/bundle/cmake/Platform/RTEMS-Initialize.cmake b/bundle/cmake/Platform/RTEMS-Initialize.cmake new file mode 100644 index 0000000..a6b491c --- /dev/null +++ b/bundle/cmake/Platform/RTEMS-Initialize.cmake @@ -0,0 +1,20 @@ +# man cmake-toolchains + +if(NOT RTEMS_BSP) + message(FATAL_ERROR "toolchain must set RTEMS_BSP") +endif() +if(NOT RTEMS_PREFIX) + message(FATAL_ERROR "toolchain must set RTEMS_PREFIX") +endif() + +set(RTEMS_TARGET_PREFIX "${RTEMS_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-rtems${CMAKE_SYSTEM_VERSION}") +set(RTEMS_TOOL_PREFIX "${RTEMS_PREFIX}/bin/${CMAKE_SYSTEM_PROCESSOR}-rtems${CMAKE_SYSTEM_VERSION}") + + +set(CMAKE_C_COMPILER ${RTEMS_TOOL_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${RTEMS_TOOL_PREFIX}-g++) +set(CMAKE_OBJCOPY ${RTEMS_TOOL_PREFIX}-objcopy) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/bundle/cmake/Platform/RTEMS.cmake b/bundle/cmake/Platform/RTEMS.cmake new file mode 100644 index 0000000..8bc504f --- /dev/null +++ b/bundle/cmake/Platform/RTEMS.cmake @@ -0,0 +1,49 @@ +# to understand Platform/ read +# https://github.com/Kitware/CMake/blob/f86d8009c6a4482c81221114a2b04b375564cc94/Source/cmGlobalGenerator.cxx#L461-L504 + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) + +set(CMAKE_EXECUTABLE_SUFFIX ".elf") + +set(CMAKE_FIND_ROOT_PATH + "${RTEMS_TARGET_PREFIX}/${RTEMS_BSP}" + "${RTEMS_TARGET_PREFIX}" +) + +set(CMAKE_SYSTEM_PREFIX_PATH ${CMAKE_FIND_ROOT_PATH}) + +set(CMAKE_SYSTEM_INCLUDE_PATH + "${RTEMS_TARGET_PREFIX}/${RTEMS_BSP}/lib/include" + "${RTEMS_TARGET_PREFIX}/include" +) +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_SYSTEM_INCLUDE_PATH}) +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_SYSTEM_INCLUDE_PATH}) + +set(CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES + "${RTEMS_TARGET_PREFIX}/${RTEMS_BSP}/lib" +) +set(CMAKE_SYSTEM_LIBRARY_PATH ${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}) + +set(CMAKE_C_FLAGS_INIT + "-B${RTEMS_TARGET_PREFIX}/${RTEMS_BSP}/lib/ -specs bsp_specs -qrtems ${RTEMS_BSP_C_FLAGS}" +) +set(CMAKE_C_FLAGS_INIT ${CMAKE_C_FLAGS_INIT}) + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-u Init ${RTEMS_BSP_LINKER_FLAGS}") +foreach(ldpart ${RTEMS_LDPARTS}) + string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " ${RTEMS_TARGET_PREFIX}/${RTEMS_BSP}/lib/${ldpart}") +endforeach() +string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -static") + +# Needed to pass to try_compile, but not to actual executables +string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -lrtemsdefaultconfig") + +# Would be nice to use instead, but break eg. CheckFunctionExists.cmake +#set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + + +# libbsd.a has some undefined symbols. eg. iflib_pseudo_detach() +string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,--gc-sections") + +# Hack so that CheckFunctionExists.cmake will find network bits normally found in a libc +set(CMAKE_REQUIRED_LIBRARIES "-lbsd") diff --git a/bundle/cmake/RTEMS.cmake@ b/bundle/cmake/RTEMS.cmake@ new file mode 100644 index 0000000..8bdc8a7 --- /dev/null +++ b/bundle/cmake/RTEMS.cmake@ @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME RTEMS) +set(CMAKE_SYSTEM_PROCESSOR @RTEMS_CPU@) +set(CMAKE_SYSTEM_VERSION @RTEMS_VERSION@) +set(RTEMS_BSP @RTEMS_BSP@) +set(RTEMS_PREFIX @RTEMS_BASE@) + +set(RTEMS_BSP_C_FLAGS "@CPU_CFLAGS@") diff --git a/src/evhelper.cpp b/src/evhelper.cpp index 7d691de..422e469 100644 --- a/src/evhelper.cpp +++ b/src/evhelper.cpp @@ -165,7 +165,16 @@ struct evbase::Pvt : public epicsThreadRunable { INST_COUNTER(evbaseRunning); try { - decltype (base) tbase(event_base_new()); + evconfig conf(event_config_new()); +#ifdef __rtems__ + /* with libbsd circa RTEMS 5.1 + * TCP peer close/reset notifications appear to be lost. + * Maybe due to absence of NOTE_EOF? + * poll() seems to work though. + */ + event_config_avoid_method(conf.get(), "kqueue"); +#endif + decltype (base) tbase(event_base_new_with_config(conf.get())); if(evthread_make_base_notifiable(tbase.get())) { throw std::runtime_error("evthread_make_base_notifiable"); } diff --git a/src/evhelper.h b/src/evhelper.h index 0c41c41..6beb0a8 100644 --- a/src/evhelper.h +++ b/src/evhelper.h @@ -25,6 +25,10 @@ // hooks for std::unique_ptr namespace std { template<> +struct default_delete { + inline void operator()(event_config* ev) { event_config_free(ev); } +}; +template<> struct default_delete { inline void operator()(event_base* ev) { event_base_free(ev); } }; @@ -170,6 +174,7 @@ public: event_base* base = nullptr; }; +typedef owned_ptr evconfig; typedef owned_ptr evevent; typedef owned_ptr evlisten; typedef owned_ptr evbufferevent; diff --git a/test/Makefile b/test/Makefile index 054a5d8..3fa7bab 100644 --- a/test/Makefile +++ b/test/Makefile @@ -102,6 +102,8 @@ testioc_SRCS += testioc_registerRecordDeviceDriver.cpp testioc_LIBS = pvxsIoc pvxs $(EPICS_BASE_IOC_LIBS) TESTS += testioc +PROD_SRCS_RTEMS += rtemsTestData.c + endif TESTPROD_HOST += mcat @@ -109,6 +111,12 @@ mcat_SRCS += mcat.cpp # not a unittest TESTSCRIPTS_HOST += $(TESTS:%=%.t) +ifdef BASE_3_15 +ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) +TESTPROD = $(TESTPROD_HOST) +TESTSCRIPTS = $(TESTSCRIPTS_HOST) +endif +endif #=========================== @@ -117,3 +125,7 @@ include $(TOP)/configure/RULES_PVXS_MODULE #---------------------------------------- # ADD RULES AFTER THIS LINE +ifdef BASE_3_15 +rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl + $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) +endif