diff --git a/.gitignore b/.gitignore index a1a054c502..4276990a53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,222 +1,104 @@ -# test outputs -**/testing/* -!**/testing/*.* -**/testing/*.characteristics -**/testing/*.datafile -**/testing/*.tree -**/testing/*.hosts -**/testing/*.txt -*.tap -*.tmp -*.trs - -Makefile -.deps -config.log -config.status -Makefile.inc -stamp-h1 -config.h -rpm/envsyms -rpm/Makefile -rpm/post_install_script -envsyms -bin/ -bin32/ -bin64/ -bin_x86/ -bin_x86_64/ -build/ -etc/ -lib/ -lib32/ -lib64/ -*.class -*.jar -*.manifest -*.egg-info -*.stamp -*.gcno -*.gcda -*.gcov -actions/actions -actions/actmon -cdu/cdu -dwscope/dwpad -dwscope/dwscope -dwscope/dwscope_remote -*.uid -javadispatcher/jDispatchMonitor -javadispatcher/jDispatcherIp -javadispatcher/jServer -javascope/scripts/ -javatraverser/jTraverser -mitdevices/acq_root_filesystem/ffs/user/MitFilesDate -setevent/setevent -wfevent/wfevent -xmdsshr/.dirstamp -camshr/cts_commands.c -# Emacs autosave files -\#*# -# vi autosave files -*~ -#vs code autosave files -*.swp -# python compiled files -*.pyc -__pycache__/ +### +### Generated files +### + +# configure_file() +_include/_mdsversion.h +mdsdcl/mdsdclVersionInfo.c +pydevices/*/_version.py +python/MDSplus/_version.py + +# deploy/gen-messages-exceptions.py +include/treeshr_messages.h +include/tdishr_messages.h +include/mdsshr_messages.h +include/tcl_messages.h +include/camshr_messages.h +include/servershr_messages.h +include/mitdevices_messages.h +include/mdsdcl_messages.h +python/MDSplus/mdsExceptions.py +mdsshr/MdsGetStdMsg.c +java/mdsplus-api/src/main/java/mds/MdsException.java -# Compiled Object files -*.slo -*.lo -*.o -*.obj +# deploy/gen-include-tdishr.py +include/tdishr.h -# Precompiled Headers -*.gch -*.pch +# deploy/gen-include-opcbuiltins.py +include/opcbuiltins.h -# Compiled Dynamic libraries -*.so -*.dylib -*.dll +# deploy/gen-python-compound.py +python/MDSplus/compound.py -# Fortran module files -*.mod +# deploy/gen-tdishr-TdiHash.py +tdishr/TdiHash.c +tdishr/TdiHash.c.in -# Compiled Static libraries -*.lai -*.la -*.a -*.lib +# deploy/gen-yacc-lex.py +mdsdcl/cmdParse.c +mdsdcl/cmdParseLex.c +mdsdcl/dcllex.h +mdsdcl/dclyacc.h +mdsdcl/mdsdclDeltatimeToSeconds.c +mdsdcl/ocldToXml.c +tdishr/TdiLex.c +tdishr/tdilex.h +tdishr/TdiYacc.c +tdishr/tdiyacc.h +treeshr/TreeFindNodeWild.c -# Executables -*.exe -*.out -*.app +# python +*.pyc +__pycache__/ +*.egg-info -# automake -aclocal.m4 -autom4te.cache +# motif +*.uid -# gfortran objects on macintosh -*.o_i386 -*.dylib_i386 -*.lnk +# yacc verbose +*.output -# python version module -_version.py -*.log +### +### Editors +### +# visual studio code .vscode/ +.cache/ -testing/MDSplus/ -testing/*Devices/ +# visual studio +.vs/ +# eclipse eclipse/ target/ .project .settings/ .classpath -# deploy/trigger.sh output -trigger.opts +# vi +*~ +*.swp -# yacc verbose -*.output +# emacs +\#*# -# bootstrap output files -LabView/Makefile.in -actions/testing/Makefile.in -configure -ChangeLog -MANIFEST.MF -_include/_mdsversion.h -docs/Makefile.in -dwscope/Makefile.in -include/camshr_messages.h -include/mdsdcl_messages.h -include/mdsplus/mdsconfig.h -include/mdsplus/mdsconfig.h.in -include/mdsshr_messages.h -include/mitdevices_messages.h -include/servershr_messages.h -include/tcl_messages.h -include/tdishr_messages.h -include/tdishr.h -include/treeshr_messages.h -include/opcbuiltins.h -java/Makefile.in -java/devicebeans/Makefile.in -java/jdevices/Makefile.in -java/jdispatcher/Makefile.in -java/jscope/Makefile.in -java/jtraverser/Makefile.in -java/jtraverser2/Makefile.in -java/mdsobjects/Makefile.in -java/mdsobjects/docs/Makefile.in -java/mdsobjects/tests/Makefile.in -java/mdsplus-api/Makefile.in -java/mdsplus-api/src/main/java/mds/MdsException.java -java/mdsplus-api/tests/Makefile.in -java/mdsplus/Makefile.in -java/tests/Makefile.in -macosx/Makefile.in -manpages/Makefile.in -math/testing/Makefile.in -mdsdcl/cmdParse.c -mdsdcl/cmdParseLex.c -mdsdcl/dcllex.h -mdsdcl/dclyacc.h -mdsdcl/mdsdclDeltatimeToSeconds.c -mdsdcl/ocldToXml.c -mdsdcl/mdsdclVersionInfo.c -mdslib/docs/Makefile.in -mdslib/testing/Makefile.in -mdsobjects/cpp/docs/Makefile.in -mdsobjects/cpp/testing/Makefile.in -mdsobjects/cpp/testing/testutils/Makefile.in -mdsshr/MdsGetStdMsg.c -mdsshr/docs/Makefile.in -mdsshr/testing/Makefile.in -mdstcpip/docs/Makefile.in -mdstcpip/docs/img/Makefile.in -mdstcpip/testing/Makefile.in -mdstcpip/zlib/Makefile.in -python/MDSplus/docs/Makefile.in -python/MDSplus/compound.py -python/MDSplus/mdsExceptions.py -python/MDSplus/tests/*_test.py -python/MDSplus/tests/Makefile.in -rpm/Makefile.in -scripts/Makefile.in -setevent/Makefile.in -tdishr/TdiHash.c -tdishr/TdiLex.c -tdishr/TdiYacc.c -tdishr/tdilex.h -tdishr/tdiyacc.h -tdishr/testing/Makefile.in -tditest/testing/Makefile.in -testing/Makefile.in -testing/backends/check/Makefile.in -testing/selftest/Makefile.in -treeshr/testing/Makefile.in -treeshr/TreeFindNodeWild.c -wfevent/Makefile.in -wfevent/testing/Makefile.in -m4/ax_git_revision.m4 - -# Generated Java binaries -java/*/classes/ -java/jdispatcher/jDispatchMonitor -java/jdispatcher/jDispatcherIp -java/jdispatcher/jServer -java/jscope/jScope -java/jscope/jScope.properties -java/jtraverser/CompileTree -java/jtraverser/DecompileTree -java/jtraverser/jTraverser -java/jtraverser2/jTraverser2 -java/jtraverser2/setupDevice +# OSX +.DS_Store + +### +### Misc +### + +[Bb]uild/ +workspace*/ +Testing/Temporary +mitdevices/acq_root_filesystem/ffs/user/MitFilesDate + +# valgrind +core.* +vgcore.* + +# deploy/trigger.sh output +trigger.opts \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2c4efd89f4..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "3rd-party-apis"] - path = 3rd-party-apis - url = https://github.com/MDSplus/3rd-party-apis.git diff --git a/3rd-party-apis b/3rd-party-apis deleted file mode 160000 index 2bb3b459ba..0000000000 --- a/3rd-party-apis +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2bb3b459ba760e29ed2ef7b18c3fcd7b7e53c92b diff --git a/CMakeDeveloperGuide.md b/CMakeDeveloperGuide.md new file mode 100644 index 0000000000..8ed957b739 --- /dev/null +++ b/CMakeDeveloperGuide.md @@ -0,0 +1,104 @@ + +# Developing MDSplus with CMake + +## Adding a Library + +1. Create a new directory (if needed) + +2. Create a CMakeLists.txt (if needed) + Multiple libraries/executables can be defined in the same CMakeLists.txt + +3. Add the following to compile and link your new library, make sure to + replace the source files with your own. + Note: All libraries will be linked as shared unless otherwise specified + if `BUILD_SHARED_LIBS=ON`, which is the default. + +```cmake +### +### ExampleShr +### + +add_library( + ExampleShr + source1.c + source2.cpp + source3.f +) +``` + +4. Linking other libraries not only adds `-lLibrary` to the linker command, + but also carries with it any `PUBLIC` settings the library had. This + includes include directories, compiler options, defines, and whatever + else is needed to use that library. + + All MDSplus libraries can be linked just by their name, and external + libraries can be linked using their interface library name. For the + dependencies that are built-in to CMake, you can find extensive documentation + on CMake's website, including what names to use here. For custom dependencies, + look in `cmake/Find*.cmake` to see what is available. + + See the `Dependencies` section of the root `CMakeLists.txt` for what libraries + are available. + +```cmake +target_link_libraries( + ExampleShr + PUBLIC + TreeShr + Threads::Threads +) +``` + +5. Configuring other options such as include directories or compiler options and + defines can be done with several functions in the form `target_*`. For more + information, see the CMake documentation for each function. + +```cmake +target_include_directories( + ExampleShr + PUBLIC + path/to/include +) + +target_compile_definitions( + ExampleShr + PRIVATE + -DVERSION=1.2.3 +) + +target_compile_options( + ExampleShr + PRIVATE + -Wno-specific-error +) +``` + +6. If you want both a static and dynamic version of your library, you need to define + a separate library with a different name all the same options. This is a bit + cumbersome, so we added a function to help named `mdsplus_add_static_copy()`. + If `BUILD_SHARED_LIBS=OFF`, then our library would already be static, and this + function call becomes a noop. + +```cmake +mdsplus_add_static_copy(ExampleShr _static_target) + +# ${_static_target} will be the name of the static library if it was made, or "" +``` + +7. Installing a library is done by marking the targets for installation. If you + used `mdsplus_add_static_copy()`, then you will want to add `${_static_target}` + to this call as well. + +```cmake +install(TARGETS ExampleShr ${_static_target}) +``` + +## Adding an Executable + +## Adding a Java JAR + +## Adding a Test + +## Adding a Dependency + +## Visual Studio Code \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..b97f98f7fc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,1654 @@ +cmake_minimum_required(VERSION 3.20 FATAL_ERROR) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "In-Source builds are no longer supported. Make a build directory, and run cmake from there instead.") +endif() + +# Allow for custom CMake modules with include() and find_package() +list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +# Disable "Built target" messages for Makefiles +set(CMAKE_TARGET_MESSAGES OFF CACHE BOOL "") +mark_as_advanced(CMAKE_TARGET_MESSAGES) + +project(MDSplus) + +enable_language(C) +enable_language(CXX) +enable_language(Fortran) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 98) + +# Custom wrapper for option() allowing defaults, types other than BOOL, and lists of values +include(MDSplusOption) + +# Query version and release information from git +include(MDSplusProjectVersion) + +### +### Download 3rd-party-apis +### + +mdsplus_option( + DOWNLOAD_3RD_PARTY_APIS BOOL + "Download https://github.com/MDSplus/3rd-party-apis to help build IDL and LabView, and to help building on Windows." + DEFAULT ON +) + +if(DOWNLOAD_3RD_PARTY_APIS) + + set(_3rd_party_apis ${CMAKE_BINARY_DIR}/3rd-party-apis-master) + + # To protect in the case of a failed download/extraction, we check if there are any + # files/directories in the folder before trying to populate it + file(GLOB _3rd_party_file_list LIST_DIRECTORIES TRUE "${_3rd_party_apis}/*") + if(NOT _3rd_party_file_list) + + set(_3rd_party_apis_url "https://github.com/MDSplus/3rd-party-apis/archive/refs/heads/master.zip") + set(_3rd_party_apis_zip ${CMAKE_BINARY_DIR}/3rd-party-apis-master.zip) + + message(STATUS "Downloading ${_3rd_party_apis_url}") + + set(_retries 0) + + while(_retries LESS 5) + file(DOWNLOAD + ${_3rd_party_apis_url} ${_3rd_party_apis_zip} + STATUS _status + ) + list(GET _status 0 _result) + list(GET _status 1 _message) + + if(_result EQUAL 0) + message(STATUS "Extracting ${_3rd_party_apis_zip}") + + # We sadly have no control over the name of the folder it gets extracted to + # For GitHub, it will always be "REPOSITORY_NAME-BRANCH" + file(ARCHIVE_EXTRACT + INPUT ${_3rd_party_apis_zip} + DESTINATION ${CMAKE_BINARY_DIR} + ) + + break() + endif() + + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) + + message(WARNING "Failed to download 3rd-party-apis: ${_message}") + math(EXPR _retries "_retries + 1") + endwhile() + + if(_retries EQUAL 3) + message(FATAL_ERROR "Failed to download 3rd-party-apis, exceeded maxium number of retries") + endif() + + endif() + +endif() + +### +### Options +### + +mdsplus_option( + PLATFORM STRING + "Intended platform for building and packaging." + OPTIONS + auto + debian + redhat + windows + macosx + DEFAULT "auto" +) + +if(PLATFORM STREQUAL "auto") + message(CHECK_START "Detecting packaging PLATFORM") + + if(WIN32) + set(PLATFORM "windows") + elseif(APPLE) + set(PLATFORM "macosx") + elseif(EXISTS /etc/os-release) + file(READ /etc/os-release _os_release) + if(_os_release MATCHES "debian") + set(PLATFORM "debian") + elseif(_os_release MATCHES "redhat") + set(PLATFORM "redhat") + endif() + endif() + + if(PLATFORM) + message(CHECK_PASS "${PLATFORM}") + else() + message(CHECK_FAIL "Failed") + endif() +endif() + +# replaces --disable-shared +mdsplus_option( + BUILD_SHARED_LIBS BOOL + "Build shared libraries." + DEFAULT ON +) + +# If no configuration types are defined, use the default list +if(NOT DEFINED CMAKE_CONFIGURATION_TYPES) + set(CMAKE_CONFIGURATION_TYPES + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo" + ) +endif() + +# We have to be careful not to overwrite the current CMAKE_BUILD_TYPE, if there is one +if(CMAKE_BUILD_TYPE STREQUAL "") + set(_force_build_type FORCE) +endif() + +# replaces --enable-debug +mdsplus_option( + CMAKE_BUILD_TYPE STRING + "Type of build to configure." + OPTIONS ${CMAKE_CONFIGURATION_TYPES} + DEFAULT "Release" + ${_force_build_type} +) + +# TODO: APPLE? +if(WIN32) + set(_default_install_dir "C:\\Program Files\\MDSplus") +else() + set(_default_install_dir "/usr/local/mdsplus") +endif() + +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(_override_install_dir FORCE) +endif() + +# replaces --prefix +mdsplus_option( + CMAKE_INSTALL_PREFIX STRING + "Where to install files to." + DEFAULT "${_default_install_dir}" + ${_override_install_dir} +) + +# Defines option(BUILD_TESTING) so can't be included in if(BUILD_TESTING) +include(CTest) + +if(BUILD_TESTING) + + mdsplus_option( + ENABLE_SELFTEST BOOL + "Include the testing/selftest directory." + DEFAULT OFF + ) + + mdsplus_option( + TEST_PORT_OFFSET STRING + "Amount to offset all ports when configuring tests" + DEFAULT OFF + ) + + # replaces --enable-valgrind + mdsplus_option( + ENABLE_VALGRIND BOOL + "Run all of the tests through Valgrind." + DEFAULT OFF + ) + + set(_valgrind_tool_list + memcheck # https://valgrind.org/docs/manual/mc-manual.html + helgrind # https://valgrind.org/docs/manual/hg-manual.html + drd # https://valgrind.org/docs/manual/drd-manual.html + exp-sgcheck # https://valgrind.org/docs/manual/sg-manual.html + ) + + mdsplus_option( + VALGRIND_TOOLS STRING + "The list of valgrind tools to search for." + DEFAULT "${_valgrind_tool_list}" + ) + + # replaces --with-valgrind-lib + mdsplus_option( + VALGRIND_LIB_DIR STRING + "Location of the valgrind library" + ) + + # The sanitizer is only avaialable for GCC and Clang + if(NOT MSVC) + + set(_sanitize_flavor_list + memory # (msan) https://clang.llvm.org/docs/MemorySanitizer.html + address # (asan) https://clang.llvm.org/docs/AddressSanitizer.html + thread # (tsan) https://clang.llvm.org/docs/ThreadSanitizer.html + undefined # (ubsan) https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + ) + + # replaces --enable-sanitize=[FLAVOR] + mdsplus_option( + ENABLE_SANITIZE STRING + "Enable compile sanitizer with flavor." + OPTIONS + OFF + ${_sanitize_flavor_list} + DEFAULT OFF + ) + + endif() + + mdsplus_option( + GENERATE_VSCODE_LAUNCH_JSON BOOL + "Generate .vscode/launch.json, this option disables itself after it is run." + DEFAULT OFF + ) + +endif() + +mdsplus_option( + PYTHON STRING + "Path to python interpreter to use for building and testing." + DEFAULT "$PYTHON" +) + +if(PYTHON STREQUAL "$PYTHON") + set(PYTHON "$ENV{PYTHON}") +endif() + +set(_enable_motif_default ON) +if(WIN32) + set(_enable_motif_default OFF) +endif() + +mdsplus_option( + ENABLE_MOTIF BOOL + "Build motif libraries and applications." + DEFAULT ${_enable_motif_default} +) + +set(_enable_sybase_default ON) +if(WIN32) + set(_enable_sybase_default OFF) +endif() + +mdsplus_option( + ENABLE_SYBASE BOOL + "Build mdssql library, and Sybase (FreeTDS) support in TDI." + DEFAULT ${_enable_sybase_default} +) + +set(_enable_hdf5_default OFF) +if(DEFINED ENV{HDF5_DIR}) + set(_enable_hdf5_default ON) +endif() + +mdsplus_option( + ENABLE_HDF5 BOOL + "Build HDF5 libraries and applications, this will default to ON if $HDF5_DIR is defined." + DEFAULT ${_enable_hdf5_default} +) + +# replaces --enable-d3d +mdsplus_option( + ENABLE_D3D BOOL + "Build MdsD3D library against d3 library located in $D3DLIB_PATH." + DEFAULT OFF +) + +# replaces --disable-java +mdsplus_option( + ENABLE_JAVA BOOL + "Build java libraries and applications." + DEFAULT ON +) + +# replaces --with-jdk +mdsplus_option( + JAVA_HOME STRING + "Location of Java Development Kit (JDK)." + DEFAULT "$JAVA_HOME" +) + +if(JAVA_HOME STREQUAL "$JAVA_HOME") + set(JAVA_HOME "$ENV{JAVA_HOME}") +endif() + +if(APPLE) + set(_java_version_description ", if JAVA_HOME is not set, this will be passed to `/usr/libexec/java_home -v $JAVA_VERSION` to find a specific version") +endif() + +mdsplus_option( + JAVA_VERSION STRING + "Minimum version of Java to search for${_java_version_description}." +) + +if(WIN32) + # replaces --disable-largefile + mdsplus_option( + ENABLE_LARGEFILE BOOL + "Enable support for large files when compiling for 32-bit." + DEFAULT ON + ) + + mdsplus_option( + TEST_WITH_WINE BOOL + "Use wine for running tests, and create a wineprefix in \${CMAKE_BUILD_DIR}/.wine" + DEFAULT OFF + ) + + mdsplus_option( + WINE_PYTHON STRING + "Path to the python executable for the installation to use when running tests in wine." + ) +endif() + +if(NOT WIN32) + # replaces --enable-perf + mdsplus_option( + ENABLE_TREE_PERF BOOL + "Collect Tree I/O performance statistics and store them in $mds_perf_filename." + DEFAULT OFF + ) +endif() + +# replaces --enable-werror +mdsplus_option( + ENABLE_WERROR BOOL + "Treat all warnings as errors (-Werror)." + DEFAULT OFF +) + +# replaces --enable-debug=profile +mdsplus_option( + ENABLE_GPROF BOOL + "Enable profiling with gprof (compile and link with -pg)." + DEFAULT OFF +) + +# replaces --with-gsi=globus-location:flavor +mdsplus_option( + GSI STRING + "Set in the form of FLAVOR or LOCATION:FLAVOR. Enables globus GSI for mdsip communications." +) + +mdsplus_option( + ENABLE_LABVIEW BOOL + "Build LV and MDSobjectsLVShr and install MDSplus LabView projects." + DEFAULT ON +) + +# replaces --with-labview= +mdsplus_option( + LABVIEW_DIR STRING + "Location of labview (i.e. /usr/local/natinst/Labview). Setting this also sets ENABLE_LABVIEW=ON." +) + +if(LABVIEW_DIR AND NOT ENABLE_LABVIEW) + + message(STATUS "Setting ENABLE_LABVIEW=ON because LABVIEW_DIR was specified") + + get_property(_helpstring CACHE ENABLE_LABVIEW PROPERTY HELPSTRING) + set(ENABLE_LABVIEW ON CACHE STRING "${_helpstring}" FORCE) + +endif() + +# replaces --with-idl= +mdsplus_option( + ENABLE_IDL BOOL + "Build idlmdsevent and idlmdswidgets against the IDL installed in IDL_DIR. If IDL_DIR is not set, the system will be searched for an installation." + DEFAULT ON +) + +mdsplus_option( + IDL_DIR STRING + "Location of IDL, or empty to indicate the system should be searched for an IDL installation. Setting this also sets ENABLE_IDL=ON." +) + +if(IDL_DIR AND NOT ENABLE_IDL) + + message(STATUS "Setting ENABLE_IDL=ON because IDL_DIR was specified") + + get_property(_helpstring CACHE ENABLE_IDL PROPERTY HELPSTRING) + set(ENABLE_IDL ON CACHE STRING "${_helpstring}" FORCE) + +endif() + +mdsplus_option( + BUILD_MITDEVICES BOOL + "Whether or not to build the mitdevices/ subdirectory" + DEFAULT ON +) + +# replaces --with-readline= +mdsplus_option( + READLINE_DIR STRING + "Location of the readline library, if not set the system will be searched" +) + +# replaces --with-xml-prefix, --with-xml-exec-prefix +mdsplus_option( + LIBXML2_DIR STRING + "Location of libxml2 library" +) + +set(_use_system_blas_default ON) +if(WIN32) + set(_use_system_blas_default OFF) +endif() + +mdsplus_option( + USE_SYSTEM_BLAS BOOL + "Use a system version of blas instead of the local copy in math/blas/" + DEFAULT ${_use_system_blas_default} +) + +# TODO: doxygen dot, man, rtf, xml, chm, chi, html +# replaces --enable/disable-doxygen-doc/dot/man/rtf/xml/chm/chi/html +mdsplus_option( + ENABLE_DOXYGEN BOOL + "Generate doxygen documentation." + DEFAULT ON +) + +set(_use_libffi_default OFF) +if(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(_use_libffi_default ON) +endif() + +mdsplus_option( + USE_LIBFFI BOOL + "Use libffi for calling external functions." + DEFAULT ${_use_libffi_default} +) + +### +### Global Configuration +### + +# ${CMAKE_C_FLAGS_INIT} is set to $ENV{CFLAGS} by default +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT} ${CMAKE_C_FLAGS}") + +# ${CMAKE_CXX_FLAGS_INIT} is set to $ENV{CXXFLAGS} by default +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_INIT} ${CMAKE_CXX_FLAGS}") + +# ${CMAKE_Fortran_FLAGS_INIT} is set to $ENV{FFLAGS} by default +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS_INIT} ${CMAKE_Fortran_FLAGS} $ENV{FCFLAGS}") + +set(CMAKE_INSTALL_BINDIR bin) +set(CMAKE_INSTALL_LIBDIR lib) + +if(PLATFORM STREQUAL "windows") + + # Windows does not differentiate between lib/ and bin/ + set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR}) + +elseif(PLATFORM STREQUAL "redhat") + + # Redhat requires the bits appended to lib and bin, e.g. lib32, bin64 + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_bits 64) + else() + set(_bits 32) + endif() + + set(CMAKE_INSTALL_BINDIR bin${_bits}) + set(CMAKE_INSTALL_LIBDIR lib${_bits}) + + set(_bindir_symlink ${CMAKE_BINARY_DIR}/bin) + set(_libdir_symlink ${CMAKE_BINARY_DIR}/lib) + + # This will create relative symlinks, which can then be install()'d, because + # CMAKE_INSTALL_[BIN/LIB]DIR are not paths + + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_INSTALL_BINDIR} ${_bindir_symlink} + ) + + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_INSTALL_LIBDIR} ${_libdir_symlink} + ) + + install( + DIRECTORY + ${_bindir_symlink} + ${_libdir_symlink} + DESTINATION . + ) + +endif() + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + +include_directories( + ${CMAKE_SOURCE_DIR}/_include + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/include/mdsplus + + # For #include <_mdsversion.h> + ${CMAKE_BINARY_DIR}/_include + + # For #include + ${CMAKE_BINARY_DIR}/include + + # For #include + ${CMAKE_BINARY_DIR}/include/mdsplus +) + +# Generate compile_commands.json +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +mark_as_advanced(CMAKE_EXPORT_COMPILE_COMMANDS) + +include(MDSplusCheckAddFlags) + +if(MINGW) + # This is not filled in correctly for mingw + set(CMAKE_DL_LIBS dl) + + # Windows should not have any prefix on the .dll/.lib files + set(CMAKE_SHARED_LIBRARY_PREFIX "") + set(CMAKE_STATIC_LIBRARY_PREFIX "") +endif() + +if(ENABLE_TREE_PERF) + add_compile_definitions(USE_TREE_PERF) +endif() + +if(MSVC) + add_compile_options(/Wall) + # TODO: Expand +else() + + # TODO: Disable for flang (family: LLVMFlang) + + mdsplus_check_add_flags( + COMPILER -Wall + ) + + mdsplus_check_add_flags( + COMPILER -Wextra + ) + + # We assume signed char everywhere + # TODO: Remove once all char's have been updated + mdsplus_check_add_flags( + COMPILER -fsigned-char + LANGUAGES C CXX + ) + + # Hide symbols by default so that only ones marked as visible are exported + mdsplus_check_add_flags( + COMPILER -fvisibility=hidden + LANGUAGES C CXX + ) + + # Disable warnings for argument type mismatches in Fortran + # TODO: Investigate why both are needed + mdsplus_check_add_flags( + COMPILER -fallow-argument-mismatch + LANGUAGES Fortran + ) + mdsplus_check_add_flags( + COMPILER -Wno-argument-mismatch + LANGUAGES Fortran + ) + + if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -warn all") + endif() + +endif() + +if(ENABLE_WERROR) + + if(MSVC) + add_compile_options(/WX) + else() + + mdsplus_check_add_flags( + COMPILER -Werror + ) + + if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -warn error") + endif() + + endif() + +endif() + +if(ENABLE_GPROF) + + string(TOLOWER "${CMAKE_BUILD_TYPE}" _build_type) + if(NOT _build_type STREQUAL "relwithdebinfo") + message(WARNING "It is recommended to use CMAKE_BUILD_TYPE=RelWithDebInfo with ENABLE_GPROF=ON") + endif() + + if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND + CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND + CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + + add_compile_options(-pg) + add_link_options(-pg) + + else() + + message(WARNING "Unable to build with support for gprof, -pg is only supported on GNU compilers") + + endif() + +endif() + +if(ENABLE_LARGEFILE) + + # If we are compiling for 32-bit + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + add_compile_definitions( + _FILE_OFFSET_BITS=64 + _LARGE_FILES + ) + endif() + +endif() + +if(ENABLE_SANITIZE IN_LIST _sanitize_flavor_list) + + mdsplus_check_add_flags( + COMPILER -fsanitize=${ENABLE_SANITIZE} + LINKER -fsanitize=${ENABLE_SANITIZE} + LANGUAGES C CXX + ) + + set(SANITIZER_ENV_MODS + "LSAN_OPTIONS=set:G_SLICE=always-malloc:suppressions=${CMAKE_SOURCE_DIR}/conf/sanitizer.supp/leak.supp" + ) + + set(_result 0) + if(ENABLE_SANITIZE STREQUAL "memory") + # + elseif(ENABLE_SANITIZE STREQUAL "address") + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-file-name=libasan.so + RESULT_VARIABLE _result + OUTPUT_VARIABLE _ld_preload + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + list(APPEND SANITIZER_ENV_MODS + "ASAN_OPTIONS=set:start_deactivated=1:exitcode=1:use_sigaltstack=0:suppressions=${CMAKE_SOURCE_DIR}/conf/sanitizer.supp/address.supp" + ) + elseif(ENABLE_SANITIZE STREQUAL "thread") + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-file-name=libtsan.so + RESULT_VARIABLE _result + OUTPUT_VARIABLE _ld_preload + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + list(APPEND SANITIZER_ENV_MODS + "TSAN_OPTIONS=set:start_deactivated=1:exitcode=1:second_deadlock_stack=1:suppressions=${CMAKE_SOURCE_DIR}/conf/sanitizer.supp/thread.supp" + ) + elseif(ENABLE_SANITIZE STREQUAL "undefined") + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-file-name=libubsan.so + RESULT_VARIABLE _result + OUTPUT_VARIABLE _ld_preload + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + list(APPEND SANITIZER_ENV_MODS + "UBSAN_OPTIONS=set:start_deactivated=1:exitcode=1:suppressions=${CMAKE_SOURCE_DIR}/conf/sanitizer.supp/undefined.supp" + ) + endif() + + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to detect LD_PRELOAD value for ${ENABLE_SANITIZE}") + endif() + + set(LD_PRELOAD "${_ld_preload}") + +endif() + +# TODO: Possibly replace these with mdsplus_check_add_flags() +foreach(_lang IN ITEMS C CXX) + if((CMAKE_${_lang}_COMPILER_ID STREQUAL "Clang" AND CMAKE_${_lang}_COMPILER_VERSION GREATER_EQUAL "15") + OR (CMAKE_${_lang}_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_${_lang}_COMPILER_VERSION GREATER_EQUAL "14")) + + # Disables the new strict prototype checking that is on by default in clang >= 15 (or apple clang >= 14) + set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} -Wno-deprecated-non-prototype") + + endif() + + if(CMAKE_${_lang}_COMPILER_ID STREQUAL "GNU" AND CMAKE_${_lang}_COMPILER_VERSION GREATER_EQUAL "13") + + # We should conform to strict aliasing, but it's going to take some work + # https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 + # + # The uninitialized and clobbered checkers are giving us some false positives as well + set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} -Wno-strict-aliasing -Wno-uninitialized -Wno-clobbered") + + endif() +endforeach() + +### +### RPATH/RUNPATH Configuration, to remove dependence on [DY]LD_LIBRARY_PATH +### + +file(RELATIVE_PATH + _rpath_relative + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} +) + +if(APPLE) + set(CMAKE_MACOSX_RPATH ON) + list(APPEND CMAKE_INSTALL_RPATH + "@loader_path" + "@executable_path/${_rpath_relative}" + ) +else() + list(APPEND CMAKE_INSTALL_RPATH + "\${ORIGIN}" + "\${ORIGIN}/${_rpath_relative}" + ) +endif() + +# TODO: Improve? +# Add the install prefix (delayed evaluation until install) +list(APPEND CMAKE_INSTALL_RPATH + $<$:\${CMAKE_INSTALL_PREFIX}/\${CMAKE_INSTALL_LIBDIR}> +) + +# Automatically add libraries we depend on to RPATH +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) + +# Investigate +# set(CMAKE_SKIP_BUILD_RPATH FALSE) +# set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + +### +### Dependencies +### + +# CMake built-in packages to find + +# Do not prefer system apple python +if(APPLE) + set(Python_FIND_FRAMEWORK LAST) +endif() + +# In order for find_package(Python) to use the python specified with -DPYTHON or $PYTHON +# we need to convert it to an absolute path +if(NOT DEFINED Python_EXECUTABLE AND NOT PYTHON STREQUAL "") + find_program(Python_EXECUTABLE "${PYTHON}") + mark_as_advanced(Python_EXECUTABLE) +endif() + +find_package(Python COMPONENTS Interpreter REQUIRED) + +# Used to easily determine Python_LIBRARIES +find_package(Python COMPONENTS Development.Embed) + +set(PYTHON "${Python_EXECUTABLE}") +set(PyLib "${Python_LIBRARIES}") + +if(TEST_WITH_WINE) + find_program(wine_EXECUTABLE wine REQUIRED) + + if(DEFINED WINE_PYTHON) + set(PYTHON "${WINE_PYTHON}") + cmake_path(GET WINE_PYTHON PARENT_PATH WINE_PYTHONHOME) + file(GLOB PyLib ${WINE_PYTHONHOME}/python*.dll) + endif() + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(WINEARCH "win64") + else() + set(WINEARCH "win32") + endif() + + set(WINEPREFIX "${CMAKE_BINARY_DIR}/.wine") + + if(NOT IS_DIRECTORY ${WINEPREFIX}) + message(STATUS "Creating wineprefix: ${WINEPREFIX}") + + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/.wine) + + # We run wine with a throwaway command in order to force it to make a WINEPREFIX that will + # then be used for all future commands. It's better to have it error out here and print a + # nice message, than to die on the first test that tries to run under wine + execute_process( + COMMAND ${CMAKE_COMMAND} -E env + WINEARCH=${WINEARCH} + WINEPREFIX=${WINEPREFIX} + ${wine_EXECUTABLE} cmd.exe /C echo test + OUTPUT_VARIABLE _output + ERROR_VARIABLE _error + RESULT_VARIABLE _result + ) + + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to create wineprefix ${WINEPREFIX}\n${_output}\n${_error}") + endif() + endif() +endif() + +# Finds the platform specific threading libraries, usually pthreads +find_package(Threads REQUIRED) + +# Finds the ZLIB compression library +find_package(ZLIB REQUIRED) + +# Finds the POSIX iconv() family of functions, which might be built into libc +# TODO: Possibly required by libxml2, can we remove it? +find_package(Iconv REQUIRED) + +# Finds libxml2 +if(NOT DEFINED LibXml2_ROOT) + set(LibXml2_ROOT "${LIBXML2_DIR}") + mark_as_advanced(LibXml2_ROOT) +endif() +find_package(LibXml2 REQUIRED) + +if(USE_SYSTEM_BLAS) + # Finds the Basic Linear Algebra Subprograms fortran functions + find_package(BLAS) + if(NOT TARGET BLAS::BLAS) + message(SEND_ERROR "Unable to find BLAS, if no package is available for your system, use -DUSE_SYSTEM_BLAS=OFF") + endif() +endif() + +# Finds the LZMA compression library +find_package(LibLZMA) + +# Custom packages to find + +# cmake/FindLibM.cmake +find_package(LibM REQUIRED) + +# cmake/FindReadline.cmake +if(NOT DEFINED Readline_ROOT) + set(Readline_ROOT "${READLINE_DIR}") +endif() +# We require at least version 5 +find_package(Readline 5 REQUIRED) + +# cmake/FindDC1394.cmake +find_package(DC1394) + +# Configuration-dependent dependencies + +if(USE_LIBFFI) + add_compile_definitions(MDSPLUS_USE_FFI) + + find_package(LibFFI REQUIRED) +endif() + +if(ENABLE_MOTIF) + # cmake/FindMotif.cmake + find_package(Motif REQUIRED) +endif() + +if(ENABLE_SYBASE AND NOT MINGW) + # cmake/FindSybase.cmake + find_package(Sybase REQUIRED) +endif() + +if(ENABLE_HDF5) + # cmake/FindHDF5.cmake + set(HDF5_ROOT "$ENV{HDF5_DIR}") + find_package(HDF5 REQUIRED) +endif() + +if(ENABLE_JAVA) + + if(APPLE AND EXISTS /usr/libexec/java_home AND JAVA_HOME STREQUAL "") + # This is a workaround for broken FindJNI.cmake on MacOS + # which only likes EXPLICIT setting of JAVA_HOME + # but also allows you to pick the jdk version + execute_process( + COMMAND /usr/libexec/java_home -v ${JAVA_VERSION} + OUTPUT_VARIABLE _output + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + + if(_output AND IS_DIRECTORY "${_output}") + set(JAVA_HOME ${_output}) + endif() + endif() + + find_package(Java ${JAVA_VERSION} COMPONENTS Runtime Development REQUIRED) + + if(WIN32) + if(DOWNLOAD_3RD_PARTY_APIS) + add_library(JNI::JNI INTERFACE IMPORTED) + + set_target_properties( + JNI::JNI + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_3rd_party_apis}/windows-jdk;${_3rd_party_apis}/windows-jdk/win32" + ) + endif() + else() + find_package(JNI REQUIRED) + endif() + + include(UseJava) + + find_program(mvn_EXECUTABLE mvn) + mark_as_advanced(mvn_EXECUTABLE) + + list(APPEND CMAKE_JAVA_COMPILE_FLAGS -encoding UTF-8) + + # Compile as Java 8 (1.8) compatible + # TODO: Remove + list(APPEND CMAKE_JAVA_COMPILE_FLAGS -source 8) + list(APPEND CMAKE_JAVA_COMPILE_FLAGS -target 8) + + if(JAVA_HOME STREQUAL "") + execute_process( + COMMAND ${Java_JAVA_EXECUTABLE} -XshowSettings:properties -version + ERROR_VARIABLE _java_properties # for some reason this outputs to stderr + ) + + if("${_java_properties}" MATCHES "java\.home = ([^\n]*)") + set(JAVA_HOME "${CMAKE_MATCH_1}") + endif() + endif() + + if(JAVA_VERSION STREQUAL "") + set(JAVA_VERSION "${Java_VERSION}") + endif() + +endif() + +if(ENABLE_IDL) + + if(IDL_DIR) + set(IDL_ROOT "${IDL_DIR}") + else() + set(IDL_ROOT + /usr/local/nv5/idl + /usr/local/harris/idl + /usr/local/exelis/idl + /usr/local/itt/idl + /usr/local/rsi/idl + ) + if(DOWNLOAD_3RD_PARTY_APIS) + list(APPEND IDL_ROOT ${_3rd_party_apis}/idl) + endif() + endif() + + # cmake/FindIDL.cmake + find_package(IDL REQUIRED) + +endif() + +if(ENABLE_D3D) + + find_library( + D3 + NAMES d3 + PATHS $ENV{D3DLIB_PATH} + REQUIRED + ) + + mark_as_advanced(D3) + +endif() + +if(GSI) + + string(REPLACE ":" ";" _gsi_list "${GSI}") # location:flavor -> location;flavor + list(LENGTH _gsi_list _gsi_list_length) + + if(_gsi_list_length LESS 2) + set(Globus_FLAVOR ${_gsi_list}) + else() + list(GET _gsi_list 0 Globus_ROOT) + list(GET _gsi_list 1 Globus_FLAVOR) + endif() + + # cmake/FindGlobus.cmake + find_package(Globus REQUIRED) + + # Only used by Roam, which is only enabled with Globus + find_package(CURL REQUIRED) + +endif() + +# TODO: Remove +if(BUILD_TESTING) + + find_library(LIBRT rt) + mark_as_advanced(LIBRT) + + if(LIBRT) + add_compile_definitions(HAVE_LIBRT) + endif() + +endif() + +if(ENABLE_VALGRIND) + + # cmake/FindValgrind.cmake + set(Valgrind_ROOT "${VALGRIND_LIB_DIR}") + string(REPLACE "," ";" Valgrind_REQUESTED_TOOL_LIST "${VALGRIND_TOOLS}") + find_package(Valgrind REQUIRED) + + if(CMAKE_C_COMPILER_ID STREQUAL "Clang" + AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "14" + AND Valgrind_VERSION VERSION_LESS "3.20") + + # dwarf is the format of compiled debug symbols + set(_force_dwarf4 "-fdebug-default-version=4") + message(STATUS "Setting ${_force_dwarf4} due to clang >= 14, and valgrind < 3.20") + + mdsplus_check_add_flags( + COMPILER ${_force_dwarf4} + LANGUAGES C CXX + ) + endif() + + set(Valgrind_FLAGS + --gen-suppressions=all + --keep-debuginfo=yes + --num-callers=64 + --trace-children=yes + --child-silent-after-fork=yes + --trace-children-skip-by-arg='*SetMdsplusFileProtection*' + ) + + set(Valgrind_memcheck_FLAGS + --leak-check=full + --show-reachable=no + ) + + set(Valgrind_helgrind_FLAGS + --history-level=full + ) + + set(Valgrind_SUPPRESSION_FILES + ${CMAKE_SOURCE_DIR}/conf/valgrind.supp/mdsplus.supp + ) + +endif() + +### +### Display user options and CMake configuration +### + +string(STRIP "${CMAKE_C_FLAGS}" CMAKE_C_FLAGS) +string(STRIP "${CMAKE_CXX_FLAGS}" CMAKE_CXX_FLAGS) +string(STRIP "${CMAKE_Fortran_FLAGS}" CMAKE_Fortran_FLAGS) + +message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME} (Processor: ${CMAKE_SYSTEM_PROCESSOR})") +message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER} (ID: ${CMAKE_C_COMPILER_ID}, Version: ${CMAKE_C_COMPILER_VERSION})") +message(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER} (ID: ${CMAKE_CXX_COMPILER_ID}, Version: ${CMAKE_CXX_COMPILER_VERSION})") +message(STATUS "CMAKE_Fortran_COMPILER: ${CMAKE_Fortran_COMPILER} (ID: ${CMAKE_Fortran_COMPILER_ID}, Version: ${CMAKE_Fortran_COMPILER_VERSION})") +message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") +message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") +message(STATUS "CMAKE_Fortran_FLAGS: ${CMAKE_Fortran_FLAGS}") + +mdsplus_print_options() + +### +### Check for includes, Libraries, and Symbols +### + +include(CheckIncludeFiles) +include(CheckSymbolExists) + +# TODO: Configure with --debug-trycompile and check that no includes are missing + +# POSIX +check_include_files("alloca.h" HAVE_ALLOCA_H) # TODO: Remove? +check_include_files("grp.h" HAVE_GRP_H) +check_include_files("pthread.h" HAVE_PTHREAD_H) +check_include_files("pwd.h" HAVE_PWD_H) +check_include_files("sys/resource.h" HAVE_SYS_RESOURCE_H) +check_include_files("sys/types.h" HAVE_SYS_TYPES_H) +check_include_files("unistd.h" HAVE_UNISTD_H) +check_include_files("sys/filio.h" HAVE_SYS_FILIO_H) +check_symbol_exists(clock_gettime "time.h" HAVE_CLOCK_GETTIME) +check_symbol_exists(fork "unistd.h" HAVE_FORK) +check_symbol_exists(getaddrinfo "netdb.h" HAVE_GETADDRINFO) +check_symbol_exists(getpwuid "pwd.h" HAVE_GETPWUID) +check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE) +check_symbol_exists(mkstemp "stdlib.h" HAVE_MKSTEMP) +check_symbol_exists(pthread_lock_global_np "pthread.h" HAVE_PTHREAD_LOCK_GLOBAL_NP) + +# FreeTDS / Sybase +set(HAVE_SYBASE ${Sybase_FOUND}) + +# VxWorks Real-Time Operating System +# TODO: Remove +check_include_files("vxWorks.h" HAVE_VXWORKS_H) + +# Readline +# We need to include for to work with mingw +check_include_files("stdio.h;readline/readline.h" HAVE_READLINE_READLINE_H) +check_symbol_exists("rl_set_signals" "stdio.h;readline/readline.h" HAVE_RL_SET_SIGNALS) + +# Linux Kernel +# We need to include for to work on some systems +check_include_files("stddef.h;scsi/sg.h" HAVE_SCSI_SG_H) + +### +### Get the current timestamp to record when the build happened +### + +find_program(date_EXECUTABLE date) +mark_as_advanced(date_EXECUTABLE) + +# TODO: Decide that string(TIMESTAMP) is good enough and remove the call to `date` +if(date_EXECUTABLE) + execute_process( + COMMAND "${date_EXECUTABLE}" + OUTPUT_VARIABLE BUILD_TIMESTAMP + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +else() + # STRING(TIMESTMAP) is missing AM/PM and the Timezone, but it is a sensible fallback + string(TIMESTAMP BUILD_TIMESTAMP "%a %d %b %Y %H:%M:%S UTC" UTC) +endif() + + +### +### Generate _include/_mdsversion.h +### + +configure_file( + ${CMAKE_SOURCE_DIR}/_include/_mdsversion.h.in + ${CMAKE_BINARY_DIR}/_include/_mdsversion.h +) + +### +### Generate include/mdsplus/mdsconfig.h +### + +if(BUILD_SHARED_LIBS) + set(SHARELIB_TYPE "${CMAKE_SHARED_LIBRARY_SUFFIX}") +else() + set(SHARELIB_TYPE "${CMAKE_STATIC_LIBRARY_SUFFIX}") +endif() + +set(_visibility_test_file ${CMAKE_BINARY_DIR}/test_visibility.c) +file(WRITE + ${_visibility_test_file} + "extern __attribute__((__visibility__(\"hidden\"))) int hiddenvar;\n" + "extern __attribute__((__visibility__(\"default\"))) int exportedvar;\n" + "extern __attribute__((__visibility__(\"hidden\"))) int hiddenfunc();\n" + "extern __attribute__((__visibility__(\"default\"))) int exportedfunc();\n" + "int main(int argc, char **argv) { return 0; }\n" +) + +try_compile( + HAVE_VISIBILITY + ${CMAKE_BINARY_DIR} + SOURCES + ${_visibility_test_file} +) + +file(REMOVE ${_visibility_test_file}) + +# This must be placed in the binary directory as it contains information +# specific to the OS/Compiler we're using +configure_file( + ${CMAKE_SOURCE_DIR}/include/mdsplus/mdsconfig.h.in + ${CMAKE_BINARY_DIR}/include/mdsplus/mdsconfig.h +) + +### +### Ensure gen-* scripts have been run +### + +include(MDSplusGenerateFiles) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-messages-exceptions.py + GENERATED_FILES + include/treeshr_messages.h + include/tdishr_messages.h + include/mdsshr_messages.h + include/tcl_messages.h + include/camshr_messages.h + include/servershr_messages.h + include/mitdevices_messages.h + include/mdsdcl_messages.h + python/MDSplus/mdsExceptions.py + mdsshr/MdsGetStdMsg.c + java/mdsplus-api/src/main/java/mds/MdsException.java +) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-include-opcbuiltins.py + GENERATED_FILES + include/opcbuiltins.h +) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-include-tdishr.py + GENERATED_FILES + include/tdishr.h +) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-python-MDSplus-compound.py + GENERATED_FILES + python/MDSplus/compound.py +) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-tdishr-TdiHash.py + GENERATED_FILES + tdishr/TdiHash.c +) + +mdsplus_generate_files( + COMMAND ${Python_EXECUTABLE} deploy/gen-yacc-lex.py + GENERATED_FILES + mdsdcl/cmdParse.c + mdsdcl/cmdParseLex.c + mdsdcl/dcllex.h + mdsdcl/dclyacc.h + mdsdcl/mdsdclDeltatimeToSeconds.c + mdsdcl/ocldToXml.c + tdishr/TdiLex.c + tdishr/tdilex.h + tdishr/TdiYacc.c + tdishr/tdiyacc.h + treeshr/TreeFindNodeWild.c +) + +### +### Generate Documentation +### + +if(ENABLE_DOXYGEN) + + find_package(Doxygen) + + if(Doxygen_FOUND) + + add_custom_target( + docs + ) + + endif() + +endif() + +### +### Libraries, Executables +### + +# Helper variables for setting file permissions during install() + +set(MODE_777 + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_WRITE GROUP_EXECUTE + WORLD_READ WORLD_WRITE WORLD_EXECUTE +) + +set(MODE_755 + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE +) + +set(MODE_644 + OWNER_READ OWNER_WRITE + GROUP_READ + WORLD_READ +) + +# Some libraries need both a Shared and a Static version, this includes a macro that helps streamline +# that and create a second library target with the suffix `-static`. For `MdsShr` for example, it will +# create the target `MdsShr-static`, which could then produce `libMdsShr.a`. If BUILD_SHARED_LIBS=OFF, +# then only the static libraries are built, and the `-static` targets will be ALIAS targets instead. +include(MDSplusAddStaticCopy) + +# Fortran Libraries + +add_subdirectory(math) +add_subdirectory(d3dshr) + +# Core Libraries + +add_subdirectory(mdsshr) +add_subdirectory(treeshr) # Requires MdsShr +add_subdirectory(tdishr) # Requires TreeShr +add_subdirectory(xtreeshr) # Requires TdiShr +add_subdirectory(mdstcpip) # Requires TdiShr +add_subdirectory(mdslib) # Requires TdiShr +add_subdirectory(xmdsshr) # Requires TdiShr +add_subdirectory(mdsmisc) # Requires XTreeShr +add_subdirectory(mdsdcl) # Requires MdsIpShr +add_subdirectory(servershr) # Requires libMdsdcl +add_subdirectory(hdf5) # Requires TdiShr +add_subdirectory(mdssql) +# add_subdirectory(mdsvme) + +# Language Binding Libraries + +add_subdirectory(mdslibidl) # Requires TdiShr +add_subdirectory(javamds) # Requires TdiShr +add_subdirectory(mdsobjects/cpp) # Requires JavaMds +add_subdirectory(mdsobjects/labview) # Requires MdsObjectsCppShr +add_subdirectory(python) +add_subdirectory(java) + +# Command Line Tools + +add_subdirectory(tdic) +add_subdirectory(tditest) +add_subdirectory(setevent) +add_subdirectory(wfevent) +# actlog is in actions/ + +# Graphical Tools + +add_subdirectory(actions) +add_subdirectory(dwscope) +add_subdirectory(traverser) +add_subdirectory(idlmdsevent) +add_subdirectory(idlmdswidgets) +# jScope, jTraverser, jTraverser2 are in java/ + +# Device Support + +add_subdirectory(mitdevices) +add_subdirectory(camshr) +add_subdirectory(remcam) # Requires CamShr +add_subdirectory(pydevices) + +# libMdsdcl commands + +add_subdirectory(tcl) +add_subdirectory(ccl) # Requires CamShr +# cts_commands is in camshr/ + +# Globus + +add_subdirectory(roam) +# MdsIpGSI is in mdstcpip/ + +# Configuration + +add_subdirectory(rpm) +add_subdirectory(scripts) +add_subdirectory(manpages) + +if(APPLE) + add_subdirectory(macosx) +endif() + +# Examples + +add_subdirectory(examples/demoadc) + +if(BUILD_TESTING) + + ### + ### Testing + ### + + if(GENERATE_VSCODE_LAUNCH_JSON) + message(STATUS "Generating .vscode/launch.json") + endif() + + include(MDSplusAddTest) + + if(ENABLE_SELFTEST) + add_subdirectory(testing/selftest) + endif() + + add_subdirectory(testing) + add_subdirectory(mdsshr/testing) + add_subdirectory(math/testing) + add_subdirectory(treeshr/testing) + add_subdirectory(mdslib/testing) + add_subdirectory(mdstcpip/testing) + add_subdirectory(tditest/testing) + add_subdirectory(wfevent/testing) + add_subdirectory(mdsobjects/cpp/testing) + add_subdirectory(python/MDSplus/tests) + + add_subdirectory(java/tests) # defines JAVA_TEST_ENV_MODS, JAVA_TEST_JAR_LIST + add_subdirectory(java/mdsobjects/tests) + add_subdirectory(java/mdsplus-api/tests) + + if(GENERATE_VSCODE_LAUNCH_JSON) + message(STATUS "Setting GENERATE_VSCODE_LAUNCH_JSON=OFF, set it again to regenerate .vscode/launch.json") + # Disable this option after it has been set, otherwise it bogs down every Configure + set(GENERATE_VSCODE_LAUNCH_JSON OFF CACHE BOOL "" FORCE) + endif() + +endif() + +if(Motif_FOUND) + + ### + ### Process *.uil files + ### + + file(GLOB_RECURSE + _uil_list + "actions/*.uil" + "dwscope/*.uil" + "traverser/*.uil" + "mitdevices/*.uil" + "idlmdswidgets/*.uil" + "xmdsshr/*.uil" + ) + + set(_uid_directory ${CMAKE_BINARY_DIR}/uid) + + if(PLATFORM STREQUAL "redhat") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_bits 64) + else() + set(_bits 32) + endif() + + set(_uid_directory_symlink ${_uid_directory}) + set(_uid_directory ${_uid_directory}${_bits}) + + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink + uid${_bits} ${_uid_directory_symlink} + ) + + install( + DIRECTORY ${_uid_directory_symlink} + DESTINATION . + ) + endif() + + file(MAKE_DIRECTORY ${_uid_directory}) + + foreach(_uil_file IN LISTS _uil_list) + cmake_path(GET _uil_file STEM LAST_ONLY _stem) + set(_uid_file ${_uid_directory}/${_stem}.uid) + + add_custom_command( + OUTPUT ${_uid_file} + DEPENDS ${_uil_file} + COMMAND ${uil_EXECUTABLE} -I${CMAKE_SOURCE_DIR}/include -o ${_uid_file} ${_uil_file} + ) + + LIST(APPEND _uid_file_list ${_uid_file}) + endforeach() + + add_custom_target( + generate-uids ALL + DEPENDS ${_uid_file_list} + ) + + install( + DIRECTORY ${_uid_directory} + DESTINATION . + ) + +endif() + +# Generate Visual Studio compatible .lib files +if(MINGW AND BUILD_SHARED_LIBS) + + # HACK: To find correct mingw-prefixed tools + # e.g. "/usr/bin/x86_64-w64-mingw32-gcc" -> "/usr/bin/x86_64-w64-mingw32-" + string(REGEX REPLACE "-([a-zA-Z_]*)$" "" _mingw_prefix "${CMAKE_C_COMPILER}") + + find_program( + gendef_EXECUTABLE REQUIRED + NAMES + "${_mingw_prefix}-gendef" + gendef + ) + + find_program( + dlltool_EXECUTABLE REQUIRED + NAMES + "${_mingw_prefix}-dlltool" + dlltool + ) + + set(_defs_dir ${CMAKE_BINARY_DIR}/defs) + file(MAKE_DIRECTORY ${_defs_dir}) + + include(MDSplusGetAllTargets) + mdsplus_get_all_targets(_all_targets) + + foreach(_target ${_all_targets}) + + get_property(_type TARGET ${_target} PROPERTY TYPE) + + if(_type STREQUAL "SHARED_LIBRARY") + + set(_lib_file "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${_target}.lib") + + add_custom_command( + COMMENT "Generating ${_target}.lib from $" + OUTPUT ${_lib_file} + DEPENDS ${_target} + # Outputs .def in the current directory + COMMAND ${gendef_EXECUTABLE} -a $ + COMMAND ${dlltool_EXECUTABLE} -d $.def -l ${_lib_file} + WORKING_DIRECTORY ${_defs_dir} + ) + + list(APPEND _lib_file_list "${_lib_file}") + + endif() + + endforeach() + + install( + FILES ${_lib_file_list} + TYPE BIN + ) + + add_custom_target( + generate-libs-from-dlls ALL + DEPENDS ${_lib_file_list} + ) + +endif() + +### +### ChangeLog +### + +include(MDSplusGit) + +if(GIT_FOUND) + + mdsplus_git(GIT_CHANGELOG log --decorate=full --no-merges) + + file(WRITE ${CMAKE_BINARY_DIR}/ChangeLog "${GIT_CHANGELOG}") + + install( + FILES ${CMAKE_BINARY_DIR}/ChangeLog + DESTINATION . + ) + +endif() + +### +### Install the remaining files and directories +### + +# TODO: Refactor and Cleanup + +install( + DIRECTORY + desktop + idl + include + LabView + matlab + nodejs + php + pixmaps + pydevices + tdi + trees + xml + ${CMAKE_BINARY_DIR}/include + DESTINATION . + USE_SOURCE_PERMISSIONS + + PATTERN "*.php" PERMISSIONS ${MODE_755} + PATTERN "*.py" PERMISSIONS ${MODE_755} + PATTERN "*.fun" PERMISSIONS ${MODE_755} + + PATTERN "*.in" EXCLUDE # Templates for generated files + PATTERN "Makefile" EXCLUDE # TODO: Remove + PATTERN "Makefile.*" EXCLUDE # TODO: Remove + PATTERN "CMakeLists.txt" EXCLUDE + + PATTERN "*.pyc" EXCLUDE + PATTERN "__pycache__" EXCLUDE +) + +install( + DIRECTORY + epics + DESTINATION . + USE_SOURCE_PERMISSIONS +) + +install( + FILES + MDSplus-License.rtf + MDSplus-License.txt + DESTINATION . +) + +if(WIN32) + install( + DIRECTORY icons + DESTINATION . + ) +endif() + +install( + FILES + setup.csh + setup.sh + DESTINATION . + PERMISSIONS ${MODE_755} +) + +install( + DIRECTORY + DESTINATION local/tdi +) + +set(MDSPLUS_CONFIGURE_COMPLETE TRUE CACHE BOOL "Inform build.py that at least one successful configure has happened" FORCE) diff --git a/CMakeMigrationGuide.md b/CMakeMigrationGuide.md new file mode 100644 index 0000000000..d231f92cef --- /dev/null +++ b/CMakeMigrationGuide.md @@ -0,0 +1,169 @@ + +# MDSplus and CMake + +MDSplus has moved build systems to CMake, the following guide should help you make the transition from `./configure` to `cmake`. + +For any questions or concerns, please reach out to slwalsh@psfc.mit.edu + +## Simple configuration + +The simplest case for building MDSplus is the following: + +``` +# Make a directory to hold the intermediate objects and generated files +mkdir build + +# Change to that directory +cd build + +# Run CMake with a path to the source directory +cmake .. + +# Build +make -j + +# Install (to /usr/local/mdsplus) +sudo make install +``` + +## Advanced configuration + +### Specifying configuration options + +Almost every option from `./configure` is available from CMake. When (re-)configuring, specify the options like so: + +``` +cmake -DENABLE_XYZ=ON -DXYZ_PATH=/path/to/xyz .. +``` + +For an interactive configuration complete with descriptions, default values, and dropdowns you can run `ccmake` or install the CMake GUI. + +To list all options and their current values, use `cmake -LAH`. + +The options from `./configure` and their CMake counterparts are listed below, along with some clarifications (`*`). + +| `./configure` | CMake | +| --------------------------------------- | ------------------------------------------------------- | +| `--disable-shared` | `BUILD_SHARED_LIBS=OFF` | +| `--enable-debug=no` | `CMAKE_BUILD_TYPE=Release`* | +| `--enable-debug=yes` | `CMAKE_BUILD_TYPE=Debug`* | +| `--enable-debug=info` | `CMAKE_BUILD_TYPE=RelWithDebInfo`* | +| `--enable-debug=profile` | `ENABLE_GPROF=ON` and `CMAKE_BUILD_TYPE=RelWithDebInfo` | +| `--prefix=[PATH]`* | `CMAKE_INSTALL_PREFIX=[PATH]`* | +| `--exec-prefix=[PATH]`* | See below | +| `--disable-largefile` | `ENABLE_LARGEFILE=OFF` | +| `--enable-perf` | `ENABLE_PERF=ON` | +| `--disable-java` | `ENABLE_JAVA=OFF` | +| `--enable-d3d` | `ENABLE_D3D=ON` | +| `--disable-xmltest` | `ENABLE_XMLTEST=OFF` | +| `--enable-valgrind` | `ENABLE_VALGRIND=ON` | +| `--enable-doxygen` | `ENABLE_DOXYGEN=ON` | +| `--enable-werror` | `ENABLE_WERROR=ON` | +| `--enable-wreturns` | | +| `--enable-wconversion` | | +| `--enable-sanitize=[FLAVOR]` | `ENABLE_SANITIZE=[FLAVOR]` | +| `--enable-silent-rules` | | +| `--disable-silent-rules` | | +| `--jars` | Never implemented | +| `--with-jdk=[PATH]` | `JAVA_HOME=[PATH]` | +| `--with-java_target=[TARGET]` | | +| `--with-java_bootclasspath=[CLASSPATH]` | | +| `--with-gsi=[LOCATION]:[FLAVOR]` | `GSI=[LOCATION]:[FLAVOR]` or `GSI=[FLAVOR]` | +| `--with-srb=[PATH]` | | +| `--with-labview=[PATH]` | `ENABLE_LABVIEW=ON` or `LABVIEW_DIR=[PATH]` | +| `--with-idl=[PATH]` | `ENABLE_IDL=ON` or `IDL_DIR=[PATH]`* | +| `--with-readline=[PATH]` | `READLINE_DIR=[PATH]` | +| `--with-xml-prefix=[PATH]` | `LIBXML2_DIR=[PATH]` | +| `--with-xml-exec-prefix=[PATH]` | | +| `--program-prefix`* | See below | +| `--program-suffix`* | See below | +| `--program-transform-name`* | See below | +| `--bindir=[PATH]` | `CMAKE_INSTALL_BINDIR=[PATH]` | +| `--libdir=[PATH]` | `CMAKE_INSTALL_LIBDIR=[PATH]` | +| `--sysconfdir=[PATH]` | `CMAKE_INSTALL_SYSCONFDIR=[PATH]` | +| `--includedir=[PATH]` | `CMAKE_INSTALL_INCLUDEDIR=[PATH]` | + +> TODO: +> --with-x, --x-includes, --x-libraries, +> --build, --host, --target, +> --*-silent-rules, maintainer-mode, +> reconfigure +> --enable-doxygen-* +> --with-docker-* +> --winebottle + + +The following environment variables are used, if present: + +* `$CC`, the C compiler to use +* `$CXX`, the C++ compiler to use +* `$FC`, the Fortran compiler to use +* `$CFLAGS`, flags appended to the compile commands for all C files +* `$CXXFLAGS`, flags appended to the compile commands for all C++ files +* `$FCFLAGS` or `$FFLAGS`, flags appended to the compile commands for all Fortran files +* `$PYTHON`, the python interpreter to use (and what `$PyLib` to use when running the tests) +* `$JAVA_HOME`, the default location to look for java tools (overridden by `JDK_DIR`) +* `$D3DLIB_PATH`, if `ENABLE_D3D=ON` this path will be searched for `libd3` +* `$HDF5_ROOT`, the path to search for the HDF5 libraries + +**CMAKE_BUILD_TYPE** + +There are actually four or more possible values: +* `Debug`, Build with debug symbols (roughly `-g` or equivalent) +* `Release`, Build with optimizations and `NDEBUG` (roughly `-O3 -DNDEBUG` or equivalent) +* `MinSizeRel`, Similar to `Release` but optimized for size (roughly `-Os -DNDEBUG` or equivalent) +* `RelWithDebInfo`, Similar to `Release` but with debug symbols (roughly `-O2 -g -NDEBUG` or equivalent) + +Run `ccmake` or the CMake GUI for a full list of possible values for your system. + +**CMAKE_INSTALL_PREFIX** + +With the move to CMake, we no longer make a distinction between the `--prefix=PREFIX` and the `--exec-prefix=EPREFIX`. If this causes issues with your workflow, contact slwalsh@psfc.mit.edu. + +**ENABLE_IDL** / **IDL_DIR** + +If `ENABLE_IDL=ON` is specified, the standard installation directories for IDL will be searched. + +If IDL is not installed in a standard directory, you can specify `IDL_DIR=[PATH]` to inform CMake of its location. Doing so will set `ENABLE_IDL=ON` automatically. + +**--program-prefix** / **--program-suffix** / **--program-transform-name** + +With the mover to CMake, we no longer support these options. If this causes issues with your workflow, contact slwalsh@psfc.mit.edu. + +### Using alternative generators + +CMake does not require you to use `make`, and in fact provides a long list of alternatives. +You can see what generators your CMake supports with: + +``` +cmake --help +``` + +Here are some examples: + +**Ninja** + +``` +mkdir build +cd build +cmake -GNinja .. +ninja +``` + +**Visual Studio** + +``` +mkdir build +cd build +cmake -G"Visual Studio 17 2022" -Ax64 .. +# Open the generated .sln +``` + +**Xcode** + +``` +mkdir build +cd build +cmake -GXcode .. +# Open the generated Xcode project +``` \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 0956af2fe8..60236e3e6f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,36 +1,182 @@ - -def OSList = [ - 'windows', - 'ubuntu18', - 'ubuntu20', - 'ubuntu22', - 'ubuntu24', - 'rhel7', - 'rhel8', - 'rhel9', - // 'alpine3.9-armhf', - // 'alpine3.9-x86_64', - // 'alpine3.9-x86', - 'debian9-64', - 'debian10-64', - 'debian11-64', - 'debian12-64', - 'test-asan', - 'test-tsan', - 'test-ubsan', +def OSList = [ + ['Ubuntu 18.04 (amd64)', 'ubuntu-18-amd64', 'docker && linux-amd64'], + ['Ubuntu 20.04 (amd64)', 'ubuntu-20-amd64', 'docker && linux-amd64'], + ['Ubuntu 22.04 (amd64)', 'ubuntu-22-amd64', 'docker && linux-amd64'], + ['Ubuntu 24.04 (amd64)', 'ubuntu-24-amd64', 'docker && linux-amd64'], + ['Ubuntu 24.04 (arm64)', 'ubuntu-24-arm64', 'docker && linux-aarch64'], + ['RHEL 7 (x86_64)', 'rhel-7-x86_64', 'docker && linux-amd64'], + ['RHEL 8 (x86_64)', 'rhel-8-x86_64', 'docker && linux-amd64'], + ['RHEL 9 (x86_64)', 'rhel-9-x86_64', 'docker && linux-amd64'], + ['Debian 10 (amd64)', 'debian-10-amd64', 'docker && linux-amd64'], + ['Debian 11 (amd64)', 'debian-11-amd64', 'docker && linux-amd64'], + ['Debian 12 (amd64)', 'debian-12-amd64', 'docker && linux-amd64'], + ['Debian 12 (arm64)', 'debian-12-arm64', 'docker && linux-aarch64'], + ['Windows (x86)', 'windows-x86', 'docker && linux-amd64'], + ['Windows (x64)', 'windows-x64', 'docker && linux-amd64'], + ['MacOSX (homebrew)', 'macosx-homebrew', 'macosx'], + ['MacOSX (macports)', 'macosx-macports', 'macosx'], + ['Address Sanitizer', 'test-asan', 'docker && linux-amd64'], + ['Thread Sanitizer', 'test-tsan', 'docker && linux-amd64'], + ['Undefined Behavior Sanitizer', 'test-ubsan', 'docker && linux-amd64'], + ['Helgrind', 'test-helgrind', 'docker && linux-amd64'], + ['Memcheck', 'test-memcheck', 'docker && linux-amd64'], ] +def setupStage() { + return { + stage("Setup") { + echo "Building on ${NODE_NAME}" + + // Useful for debugging + sh 'printenv' + + // This shouldn't be needed, but just in case + cleanWs disableDeferredWipeout: true, deleteDirs: true + + unstash 'source' + } + } +} + +def testStage(os) { + + def extraArgs = "" + + if (os.startsWith("macosx-")) { // || OS.startsWith("windows-") + // Required to isolate runs on systems that don't have docker networks to do the isolation + def offset = (EXECUTOR_NUMBER as int) * 1000 + extraArgs += "-DTEST_PORT_OFFSET=${offset}" + } + else { + extraArgs += "--dockernetwork=jenkins-${EXECUTOR_NUMBER}" + } + + return { + stage("Build & Test") { + try { + // TODO: Adjust -j value + sh "deploy/build.py -j8 --os=${os} --build --test -DCMAKE_BUILD_TYPE=Debug --dockerpull --output-junit ${extraArgs}" + } + finally { + junit skipPublishingChecks: true, testResults: "workspace-${os}/mdsplus-junit.xml", keepLongStdio: true + } + } + } +} + +def packageStage(os) { + return { + stage("Build & Package") { + // TODO: Adjust -j value + sh "deploy/build.py -j8 --os=${os} --build --package -DCMAKE_BUILD_TYPE=Release" + dir("workspace-${os}") { + stash name: "packages-${os}", includes: "packages/**/*" + stash name: "dist-${os}", includes: "mdsplus-publish.json,dist/**/*" + } + } + } +} + +def cleanStage() { + return { + stage("Clean") { + // Collect valgrind core dumps + archiveArtifacts artifacts: "**/core", followSymlinks: false, allowEmptyArchive: true + + cleanWs disableDeferredWipeout: true, deleteDirs: true + } + } +} + +def distributions = OSList.collectEntries { + info -> [ "${info[0]}": { + def (name, os, label) = info + + node (label) { + stage(name) { + ansiColor('xterm') { + try { + setupStage().call() + testStage(os).call() + if (!os.startsWith("test-")) { + packageStage(os).call() + } + } + finally { + cleanStage().call() + } + } + } + } + }] +} + +def localTest(name, label, testStages) { + return { + stage(name) { + node(label) { + ansiColor('xterm') { + try { + setupStage().call() + + stage("Build") { + // TODO: Adjust -j value + sh "deploy/build.py -j8 --build --install -DCMAKE_BUILD_TYPE=Debug" + } + + testStages.call() + } + finally { + cleanStage().call() + } + } + } + } + } +} + +distributions['IDL'] = localTest('IDL', 'linux-amd64', { + stage("Test") { + try { + withEnv(["MDSPLUS_DIR=${WORKSPACE}/workspace/install/usr/local/mdsplus"]) { + sh """ + set +x + . \$MDSPLUS_DIR/setup.sh + export PYTHONPATH=\$MDSPLUS_DIR/python/ + set -x + ./idl/testing/run_tests.py + """ + } + } + finally { + // junit skipPublishingChecks: true, testResults: "mdsplus-junit.xml", keepLongStdio: true + } + } +}) + +distributions['MATLAB'] = localTest('MATLAB', 'linux-amd64', { + stage("Test") { + withEnv(["MDSPLUS_DIR=${WORKSPACE}/workspace/install/usr/local/mdsplus"]) { + sh """ + set +x + . \$MDSPLUS_DIR/setup.sh + export PYTHONPATH=\$MDSPLUS_DIR/python/ + set -x + echo "Testing MATLAB" + """ + } + } +}) + def AdminList = [ - 'AndreaRigoni', + 'dgarnier', 'GabrieleManduchi', + 'heidthecamp', 'joshStillerman', 'mwinkel-dev', 'santorofer', - 'tfredian', 'WhoBrokeTheBuild', 'zack-vii', - 'dgarnier', - 'heidthecamp', ] def schedule = ""; @@ -41,29 +187,29 @@ if (BRANCH_NAME == "stable") { schedule = "0 19 * * *"; } -def new_version = '0.0.0'; def new_tag = null; -def release_file_list = []; - pipeline { - agent any + agent { + label 'built-in' + } options { skipDefaultCheckout() timeout(time: 1, unit: 'HOURS') } + triggers { cron(schedule) issueCommentTrigger('(?i).*retest\\s+this\\s+please.*') } stages { - + stage('Setup') { steps { sh 'printenv' - + script { // is PR if (env.CHANGE_ID) { @@ -86,124 +232,39 @@ pipeline { // This shouldn't be needed, but just in case cleanWs disableDeferredWipeout: true, deleteDirs: true - } - } - - stage("Calculate Version") { - when { - anyOf { - branch 'alpha'; - branch 'stable'; + + retry(3) { + checkout scm; } - } - steps { - script { - ws("${WORKSPACE}/publish") { - checkout scm; - new_version = sh( - script: "./deploy/get_new_version.py", - returnStdout: true - ).trim() - - if (new_version == '0.0.0') { - error "Failed to calculate new version" - } - + script { + def new_version = sh( + script: "/usr/bin/python3 deploy/get_new_version.py", + returnStdout: true + ).trim() + + if (new_version != '0.0.0') { new_tag = "${BRANCH_NAME}_release-" + new_version.replaceAll("\\.", "-") echo "Calculated new version to be ${new_version}" - } + + sh "git tag ${new_tag} || true" + } } + + // By default it excludes .git/ + stash name: 'source', includes: '**', useDefaultExcludes: false } } - + stage('Distributions') { steps { script { - parallel OSList.collectEntries { - OS -> [ "${OS} Build & Test": { - stage("${OS} Build & Test") { - ws("${WORKSPACE}/${OS}") { - def network = "jenkins-${EXECUTOR_NUMBER}-${OS}" - - stage("${OS} Clone") { - checkout scm; - - if (new_tag) { - sh "git tag ${new_tag} || true" - } - } - - stage("${OS} Bootstrap") { - sh "./deploy/build.sh --os=bootstrap --branch=${BRANCH_NAME} --dockernetwork=${network}" - - if (OS.endsWith("armhf")) { - sh "docker run --rm --privileged multiarch/qemu-user-static:register --reset" - } - } - - stage("${OS} Test") { - try { - sh "./deploy/build.sh --os=${OS} --test --dockernetwork=${network}" - } - finally { - sh "./deploy/tap-to-junit.py --junit-suite-name=${OS}" - junit skipPublishingChecks: true, testResults: 'mdsplus-junit.xml', keepLongStdio: true - - echo "Testing complete" - } - } - - if (!OS.startsWith("test-")) { - stage("${OS} Release") { - sh "./deploy/build.sh --os=${OS} --release --branch=${BRANCH_NAME} --version=${new_version} --dockernetwork=${network} --keys=/mdsplus/certs" - - findFiles(glob: "packages/*.tgz").each { - file -> release_file_list.add(WORKSPACE + "/" + file.path) - } - - findFiles(glob: "packages/*.exe").each { - file -> release_file_list.add(WORKSPACE + "/" + file.path) - } - } - } - } - } - }] - } + parallel distributions } } } - - stage('Additional Testing') { - parallel { - stage("Test IDL") { - steps { - // The IDL tests have to be run with the same OS as the builder - ws("${WORKSPACE}/ubuntu22") { - withEnv(["MDSPLUS_DIR=${WORKSPACE}/tests/64/buildroot"]) { - sh """ - set +x - . \$MDSPLUS_DIR/setup.sh - export PYTHONPATH=\$MDSPLUS_DIR/python/ - set -x - ./idl/testing/run_tests.py - """ - } - } - } - } - - stage("Test MATLAB") { - steps { - echo "Testing MATLAB" - // TODO - } - } - } - } - + stage('Publish') { when { allOf { @@ -215,47 +276,69 @@ pipeline { triggeredBy 'TimerTrigger' } } + steps { script { + ansiColor('xterm') { + for (info in OSList) { + def (name, os, label) = info - - parallel OSList.findAll{ OS -> (!OS.startsWith("test-")) }.collectEntries { - OS -> [ "${OS} Publish": { - stage("${OS} Publish") { - ws("${WORKSPACE}/${OS}") { - sh "./deploy/build.sh --os=${OS} --publish --branch=${BRANCH_NAME} --version=${new_version} --keys=/mdsplus/certs --publishdir=/mdsplus/dist" - } + if (os.startsWith("test-")) { + continue; } - }] - } - stage("Publish to GitHub") { - ws("${WORKSPACE}/publish") { - echo "Creating GitHub Release and Tag for ${new_tag}" - withCredentials([ - usernamePassword( - credentialsId: 'MDSplusJenkins', - usernameVariable: 'GITHUB_APP', - passwordVariable: 'GITHUB_ACCESS_TOKEN' - )]) { - - // TODO: Protect against spaces in filenames - def release_file_list_arg = release_file_list.join(" ") - sh "./deploy/create_github_release.py --tag ${new_tag} --api-token \$GITHUB_ACCESS_TOKEN ${release_file_list_arg}" + unstash "packages-${os}" + unstash "dist-${os}" + + sh "deploy/publish.py --dist-dir=/opt/fakedist --cert-dir=/mdsplus/certs --publish-info=mdsplus-publish.json" + } + + def release_file_list = []; + + dir("packages") { + sh "ls" + + def prefix = pwd() + findFiles(glob: "*.tgz,*.exe").each { + file -> release_file_list.add("${prefix}/${file.path}") } + archiveArtifacts artifacts: "*.tgz,*.exe", followSymlinks: false } + + cleanWs disableDeferredWipeout: true, deleteDirs: true + + echo "Creating GitHub Release and Tag for ${new_tag}" + + release_file_list.each { + item -> echo "${item}" + } + + // withCredentials([ + // usernamePassword( + // credentialsId: 'MDSplusJenkins', + // usernameVariable: 'GITHUB_APP', + // passwordVariable: 'GITHUB_ACCESS_TOKEN' + // )]) { + + // // TODO: Protect against spaces in filenames + // def release_file_list_arg = release_file_list.join(" ") + // sh "./deploy/create_github_release.py --tag ${new_tag} --api-token \$GITHUB_ACCESS_TOKEN ${release_file_list_arg}" + // } } } } } } + + // TODO: UPDATE ALL DEVELOPERS post { - always { - archiveArtifacts artifacts: "**/test-suite.tap,**/core", followSymlinks: false - - cleanWs disableDeferredWipeout: true, deleteDirs: true + failure { + // if alpha/stable + mail subject: 'Build is failing', + body: "Build is failing: ${BUILD_URL}", + to: 'slwalsh@psfc.mit.edu,heidcamp@mit.edu' } } -} +} \ No newline at end of file diff --git a/README.md b/README.md index ebf76de5ce..631533e587 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build Status](https://jenkins.mdsplus.org/buildStatus/icon?job=MDSplus%2Falpha) +![Build Status](https://jenkins.mdsplus.org/buildStatus/icon?job=MDSplus%2Fcmake) ## We want to know who you are The MDSplus developers want to know who you are. If you or your site is using MDSplus please fill the following survey. We promise not to share your contact information. Do not assume that other's from your institution have also filled this out, we will combine the results. diff --git a/_include/_mdsversion.h.in b/_include/_mdsversion.h.in index 99a298a9cc..a467d85193 100644 --- a/_include/_mdsversion.h.in +++ b/_include/_mdsversion.h.in @@ -3,6 +3,8 @@ #include #include +// LIBPREFIX is defined to a different value for each library so that the following symbols don't overlap + #define CONCAT2(a, b) a##b #define CONCAT(a, b) CONCAT2(a, b) #define VERSIONCONST CONCAT(LIBPREFIX, Version) @@ -18,37 +20,24 @@ const mds_version_t VERSIONCONST = { "@RELEASE_BRANCH@", }; -static pthread_once_t once = PTHREAD_ONCE_INIT; -static char tag[64]; -static mdsdsc_t RELEASE_D = { 0, DTYPE_T, CLASS_S, tag }; - -static const char release_date[64] = "@RELEASE_DATE@"; - -static void buildtag() -{ - RELEASE_D.length = snprintf(tag, sizeof(tag), "%.12s_release-%d-%d-%d", - VERSIONCONST.BRANCH, - VERSIONCONST.MAJOR, - VERSIONCONST.MINOR, - VERSIONCONST.MICRO); -} - EXPORT -const char *GETRELEASE() +const char * GETRELEASE() { - pthread_once(&once, buildtag); + static char tag[] = "@RELEASE_BRANCH@_release-@RELEASE_MAJOR@-@RELEASE_MINOR@-@RELEASE_RELEASE@"; return tag; } EXPORT -const mdsdsc_t *GETRELEASEDSC() +const mdsdsc_t * GETRELEASEDSC() { - pthread_once(&once, buildtag); - return &RELEASE_D; + static char tag[] = "@RELEASE_BRANCH@_release-@RELEASE_MAJOR@-@RELEASE_MINOR@-@RELEASE_RELEASE@"; + static mdsdsc_t dsc = { sizeof(tag), DTYPE_T, CLASS_S, tag }; + return &dsc; } EXPORT const char *GETRELEASEDATE() { + static char release_date[64] = "@BUILD_TIMESTAMP@"; return release_date; } diff --git a/actions/CMakeLists.txt b/actions/CMakeLists.txt new file mode 100644 index 0000000000..1cb8b9a132 --- /dev/null +++ b/actions/CMakeLists.txt @@ -0,0 +1,68 @@ + +### +### actlog +### + +add_executable( + actlog + actlog.c +) + +target_link_libraries( + actlog + PRIVATE + MdsServerShr +) + +install(TARGETS actlog) + +if(TARGET XmdsShr) + + ### + ### actions + ### + + add_executable( + actions + actions.c + ) + + target_link_libraries( + actions + PRIVATE + XmdsShr + ) + + install(TARGETS actions) + +endif() + +if(TARGET Motif::Motif) + + ### + ### actmon + ### + + add_executable( + actmon + actmon.c + ) + + if(WIN32) + target_sources( + actmon + PRIVATE + icon.rc + ) + endif() + + target_link_libraries( + actmon + PRIVATE + Motif::Motif + MdsServerShr + ) + + install(TARGETS actmon) + +endif() \ No newline at end of file diff --git a/bootstrap b/bootstrap index dcdf20a13d..a0ce2d6f53 100755 --- a/bootstrap +++ b/bootstrap @@ -1,62 +1,12 @@ -#! /bin/sh -cd $(dirname $0) - -check() { which $1 > /dev/null 2>&1; } -unset abort -testprog() { -# $1 prog, $2 package -if ! check $1 -then - export abort=$? - echo "Please install package providing '$1' in order to bootstrap" - shift - echo "The required package may be named $@." - echo "We recommend using docker if available:" - echo " deploy/build.sh --os=bootstrap" -fi -} - - -if check python3 -then PYTHON=python3 -elif check python2 -then PYTHON=python2 -else PYTHON=python -fi - -testprog aclocal automake -testprog autoheader autoconf -testprog automake automake -testprog autoconf autoconf -testprog $PYTHON python2 or python3 -testprog bison bison -testprog flex flex -export PYTHON - -if [ ! -z $abort ] -then - exit $abort -fi - -conf/update_submodules - -python/generate_tests - -deploy/git_revision.sh # must be done before autoconf - -aclocal -I ./m4 - -autoheader - -# libtoolize - -automake --add-missing - -autoconf - -$PYTHON deploy/gen-include-opcbuiltins.py -$PYTHON deploy/gen-include-tdishr.py -$PYTHON deploy/gen-messages-exceptions.py -$PYTHON deploy/gen-python-MDSplus-compound.py -$PYTHON deploy/gen-tdishr-TdiHash.py -$PYTHON deploy/gen-yacc-lex.py +#!/bin/sh + +python3 deploy/gen-messages-exceptions.py +python3 deploy/gen-include-opcbuiltins.py +python3 deploy/gen-include-tdishr.py +python3 deploy/gen-python-MDSplus-compound.py +python3 deploy/gen-tdishr-TdiHash.py +python3 deploy/gen-yacc-lex.py + +echo "==============================================================================================" +echo "This is no longer required, please run CMake directly and files will be bootstrapped as needed" +echo "==============================================================================================" diff --git a/camshr/CMakeLists.txt b/camshr/CMakeLists.txt new file mode 100644 index 0000000000..d3a8706d38 --- /dev/null +++ b/camshr/CMakeLists.txt @@ -0,0 +1,110 @@ + +if(HAVE_SCSI_SG_H AND NOT MSVC) + + ### + ### CamShr + ### + + set(MAJOR 1) + set(MINOR 8) + + add_library( + CamShr + add_entry.c + bisearch.c + cam_functions.c + check_for_file.c + check_sema4.c + commit_entry.c + compare_str.c + copy.c + create_sema4.c + create_tmp_file.c + debug.c + expand_db.c + get_crate_status.c + get_db_file_size.c + get_file_count.c + get_file_name.c + get_scsi_device_number.c + global.c + issort.c + lock_file.c + lookup_entry.c + map_data_file.c + map_scsi_device.c + msg.c + parse_crate_db.c + parse_cts_db.c + QueryHighwayType.c + remove_entry.c + scsi_io.c + ScsiSystemStatus.c + turn_crate_on_off_line.c + unlock_file.c + xlate_logicalname.c + RemCamMulti.c + RemCamSingle.c + RemCamIosb.c + ) + + target_link_options( + CamShr + PRIVATE + -nostartfiles + ) + + target_link_libraries( + CamShr + PUBLIC + MdsIpShr + ) + + set_target_properties( + CamShr + PROPERTIES + # Creates symlink for .so -> .so.MAJOR.MINOR + VERSION "${MAJOR}.${MINOR}" + # Creates symlink for .so -> .so.MAJOR + SOVERSION "${MAJOR}" + ) + + install(TARGETS CamShr) + + ### + ### cts_commands + ### + + add_library( + cts_commands + verbs.c + ) + + target_link_libraries( + cts_commands + PUBLIC + libMdsdcl + CamShr + ) + + install(TARGETS cts_commands) + + ### + ### Scripts + ### + + set(_script_list + mdscts + ) + + file(COPY ${_script_list} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ) + + install( + FILES ${_script_list} + TYPE BIN + PERMISSIONS ${MODE_755} + ) + +endif() \ No newline at end of file diff --git a/camshr/cts b/camshr/mdscts similarity index 100% rename from camshr/cts rename to camshr/mdscts diff --git a/ccl/CMakeLists.txt b/ccl/CMakeLists.txt new file mode 100644 index 0000000000..df15614e1d --- /dev/null +++ b/ccl/CMakeLists.txt @@ -0,0 +1,40 @@ + +### +### ccl_commands +### + +add_library( + ccl_commands + ccl_verbs.c +) + +target_link_libraries( + ccl_commands + PUBLIC + libMdsdcl + CamShr +) + +install(TARGETS ccl_commands) + +### +### Scripts +### + +if(WIN32) + set(_ext ".bat") +endif() + +set(_script_list + mdsccl${_ext} +) + +file(COPY ${_script_list} + DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} +) + +install( + FILES ${_script_list} + TYPE BIN + PERMISSIONS ${MODE_755} +) \ No newline at end of file diff --git a/cmake/FindDC1394.cmake b/cmake/FindDC1394.cmake new file mode 100644 index 0000000000..38b80acb82 --- /dev/null +++ b/cmake/FindDC1394.cmake @@ -0,0 +1,80 @@ +# FindDC1394.cmake +# +# Finds both dc1394 and raw1394 for use with IEEE1394 cameras +# +# This will define the following variables +# +# DC1394_FOUND +# DC1394_INCLUDE_DIRS +# DC1394_dc1394_LIBRARY +# DC1394_raw1394_LIBRARY +# DC1394_LIBRARIES +# +# and the following imported targets +# +# DC1394::DC1394 +# +# The following variables can be set as arguments +# +# DC1394_ROOT +# + +find_path( + DC1394_INCLUDE_DIRS + NAMES dc1394/dc1394.h + PATH_SUFFIXES + include +) + +find_library( + DC1394_dc1394_LIBRARY + NAMES dc1394 + PATH_SUFFIXES + lib +) + +find_library( + DC1394_raw1394_LIBRARY + NAMES raw1394 + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + DC1394 + REQUIRED_VARS # The first one is displayed in the message + DC1394_dc1394_LIBRARY + DC1394_INCLUDE_DIRS + # DC1394_raw1394_LIBRARY +) + +if(DC1394_FOUND) + + set(DC1394_LIBRARIES ${DC1394_dc1394_LIBRARY}) + if(DC1394_raw1394_LIBRARY) + list(APPEND DC1394_LIBRARIES ${DC1394_raw1394_LIBRARY}) + endif() + + if(NOT TARGET DC1394::DC1394) + + add_library(DC1394::DC1394 INTERFACE IMPORTED) + + set_target_properties( + DC1394::DC1394 + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${DC1394_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${DC1394_LIBRARIES}" + ) + + endif() + +endif() + +mark_as_advanced( + DC1394_ROOT + DC1394_INCLUDE_DIRS + DC1394_LIBRARIES + DC1394_dc1394_LIBRARY + DC1394_raw1394_LIBRARY +) diff --git a/cmake/FindGlobus.cmake b/cmake/FindGlobus.cmake new file mode 100644 index 0000000000..c42a986c9c --- /dev/null +++ b/cmake/FindGlobus.cmake @@ -0,0 +1,164 @@ +# FindGlobus.cmake +# +# Finds the Globus Toolkit (or Grid Community Toolkit) +# +# This will define the following variables +# +# Globus_FOUND +# Globus_INCLUDE_DIRS +# Globus_LIBRARIES +# Globus_globus_common_LIBRARY +# Globus_globus_gridmap_callout_error_LIBRARY +# Globus_globus_gss_assist_LIBRARY +# Globus_globus_gssapi_error_LIBRARY +# Globus_globus_gssapi_gsi_LIBRARY +# Globus_globus_xio_gsi_driver_LIBRARY +# Globus_globus_xio_LIBRARY +# +# and the following imported targets +# +# Globus::Globus +# +# The following variables can be set as arguments +# +# Globus_ROOT +# + +find_package(PkgConfig QUIET) + +pkg_check_modules( + _Globus_PC QUIET + globus-common + globus-gridmap-callout-error + globus-gss-assist + globus-gssapi-error + globus-gssapi-gsi + globus-xio-gsi-driver + globus-xio +) + +find_path( + Globus_INCLUDE_DIRS + NAMES globus_common.h + PATHS + ${_Globus_PC_INCLUDE_DIRS} + PATH_SUFFIXES + include +) + +find_library( + Globus_globus_common_LIBRARY + NAMES globus_common + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_gridmap_callout_error_LIBRARY + NAMES globus_gridmap_callout_error + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_gss_assist_LIBRARY + NAMES globus_gss_assist + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_gssapi_error_LIBRARY + NAMES globus_gssapi_error + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_gssapi_gsi_LIBRARY + NAMES globus_gssapi_gsi + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_xio_LIBRARY + NAMES globus_xio + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Globus_globus_xio_gsi_driver_LIBRARY + NAMES globus_xio_gsi_driver + PATHS + ${_Globus_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Globus + REQUIRED_VARS # The first one is displayed in the message + Globus_globus_common_LIBRARY + Globus_INCLUDE_DIRS + Globus_globus_gridmap_callout_error_LIBRARY + Globus_globus_gss_assist_LIBRARY + Globus_globus_gssapi_error_LIBRARY + Globus_globus_gssapi_gsi_LIBRARY + Globus_globus_xio_gsi_driver_LIBRARY + Globus_globus_xio_LIBRARY +) + +if(Globus_FOUND) + + set(Globus_LIBRARIES + ${Globus_globus_common_LIBRARY} + ${Globus_globus_gridmap_callout_error_LIBRARY} + ${Globus_globus_gss_assist_LIBRARY} + ${Globus_globus_gssapi_error_LIBRARY} + ${Globus_globus_gssapi_gsi_LIBRARY} + ${Globus_globus_xio_gsi_driver_LIBRARY} + ${Globus_globus_xio_LIBRARY} + ) + + if(NOT TARGET Globus::Globus) + + add_library(Globus::Globus INTERFACE IMPORTED) + + set_target_properties( + Globus::Globus + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Globus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${Globus_LIBRARIES}" + ) + + endif() + +endif() + +mark_as_advanced( + Globus_ROOT + Globus_INCLUDE_DIRS + Globus_LIBRARIES + Globus_globus_common_LIBRARY + Globus_globus_gridmap_callout_error_LIBRARY + Globus_globus_gss_assist_LIBRARY + Globus_globus_gssapi_error_LIBRARY + Globus_globus_gssapi_gsi_LIBRARY + Globus_globus_xio_gsi_driver_LIBRARY + Globus_globus_xio_LIBRARY +) diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake new file mode 100644 index 0000000000..7b13bd9f36 --- /dev/null +++ b/cmake/FindHDF5.cmake @@ -0,0 +1,71 @@ +# FindHDF5.cmake +# +# Finds the HDF5 data format library +# +# This will define the following variables +# +# HDF5_FOUND +# HDF5_INCLUDE_DIRS +# HDF5_LIBRARIES +# +# and the following imported targets +# +# HDF5::HDF5 +# +# The following variables can be set as arguments +# +# HDF5_ROOT +# + +find_package(PkgConfig QUIET) + +pkg_check_modules(_HDF5_PC QUIET hdf5) + +find_path( + HDF5_INCLUDE_DIRS + NAMES hdf5.h + PATHS + ${_HDF5_PC_INCLUDE_DIRS} + PATH_SUFFIXES + include +) + +find_library( + HDF5_LIBRARIES + NAMES hdf5 + PATHS + ${_HDF5_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + HDF5 + REQUIRED_VARS # The first one is displayed in the message + HDF5_LIBRARIES + HDF5_INCLUDE_DIRS +) + +if(HDF5_FOUND) + + if(NOT TARGET HDF5::HDF5) + + add_library(HDF5::HDF5 INTERFACE IMPORTED) + + set_target_properties( + HDF5::HDF5 + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${HDF5_LIBRARIES}" + ) + + endif() + +endif() + +mark_as_advanced( + HDF5_ROOT + HDF5_INCLUDE_DIRS + HDF5_LIBRARIES +) \ No newline at end of file diff --git a/cmake/FindIDL.cmake b/cmake/FindIDL.cmake new file mode 100644 index 0000000000..4e21fbe70f --- /dev/null +++ b/cmake/FindIDL.cmake @@ -0,0 +1,62 @@ +# FindIDL.cmake +# +# Finds IDL's export.h +# +# This will define the following variables +# +# IDL_FOUND +# IDL_INCLUDE_DIRS +# +# and the following imported targets +# +# IDL::IDL +# +# The following variables can be set as arguments +# +# IDL_ROOT +# + +find_path( + IDL_INCLUDE_DIRS + NAMES export.h + PATH_SUFFIXES + external +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + IDL + REQUIRED_VARS + IDL_INCLUDE_DIRS +) + +if(IDL_FOUND) + + if(NOT TARGET IDL::IDL) + + add_library(IDL::IDL INTERFACE IMPORTED) + + set_target_properties( + IDL::IDL PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${IDL_INCLUDE_DIRS}" + ) + + if(APPLE) + + # Apple does not support weak linking by default + set_target_properties( + IDL::IDL + PROPERTIES + INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup,-no_fixup_chains" + ) + + endif() + + endif() + +endif() + +mark_as_advanced( + IDL_ROOT + IDL_INCLUDE_DIRS +) diff --git a/cmake/FindLibFFI.cmake b/cmake/FindLibFFI.cmake new file mode 100644 index 0000000000..d482b3c8f9 --- /dev/null +++ b/cmake/FindLibFFI.cmake @@ -0,0 +1,71 @@ +# FindLibFFI.cmake +# +# Finds libLibFFI +# +# This will define the following variables +# +# LibFFI_FOUND +# LibFFI_INCLUDE_DIRS +# LibFFI_LIBRARIES +# +# and the following imported targets +# +# LibFFI::LibFFI +# +# The following variables can be set as arguments +# +# LibFFI_ROOT +# + +find_package(PkgConfig QUIET) + +pkg_check_modules(_LibFFI_PC QUIET ffi) + +find_path( + LibFFI_INCLUDE_DIRS + NAMES ffi.h + HINTS + ${_LibFFI_PC_INCLUDE_DIRS} + PATH_SUFFIXES + include + include/ffi +) + +find_library( + LibFFI_LIBRARIES + NAMES ffi + HINTS + ${_LibFFI_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + LibFFI + REQUIRED_VARS + LibFFI_LIBRARIES + LibFFI_INCLUDE_DIRS +) + +if(LibFFI_FOUND) + + if(NOT TARGET LibFFI::LibFFI) + + add_library(LibFFI::LibFFI INTERFACE IMPORTED) + + set_target_properties( + LibFFI::LibFFI + PROPERTIES + INTERFACE_LINK_LIBRARIES "${LibFFI_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${LibFFI_INCLUDE_DIRS}" + ) + + endif() + +endif() + +mark_as_advanced( + LibFFI_INCLUDE_DIRS + LibFFI_LIBRARIES +) diff --git a/cmake/FindLibM.cmake b/cmake/FindLibM.cmake new file mode 100644 index 0000000000..f1c0805951 --- /dev/null +++ b/cmake/FindLibM.cmake @@ -0,0 +1,46 @@ +# FindLibM.cmake +# +# Finds libm, if present on this system, otherwise creates an empty target +# +# This will define the following variables +# +# LibM_FOUND +# LibM_LIBRARIES +# +# and the following imported targets +# +# LibM::LibM +# + +set(LibM_FOUND TRUE) + +find_library( + LibM_LIBRARIES + NAMES m +) + +mark_as_advanced( + LibM_FOUND + LibM_LIBRARIES +) + +if(NOT TARGET LibM::LibM) + + add_library(LibM::LibM INTERFACE IMPORTED) + + if(LibM_LIBRARIES) + + set_target_properties( + LibM::LibM + PROPERTIES + INTERFACE_LINK_LIBRARIES "${LibM_LIBRARIES}" + ) + + endif() + +endif() + +mark_as_advanced( + LibM_ROOT + LibM_LIBRARIES +) \ No newline at end of file diff --git a/cmake/FindMDSplus.cmake b/cmake/FindMDSplus.cmake new file mode 100644 index 0000000000..b4bb7d48d2 --- /dev/null +++ b/cmake/FindMDSplus.cmake @@ -0,0 +1,319 @@ +# FindMDSplus.cmake +# +# Finds MDSplus +# +# This will define the following variables +# +# MDSplus_FOUND +# MDSPLUS_DIR +# MDSplus_INCLUDE_DIRS +# MDSplus_MdsShr_LIBRARY +# MDSplus_TreeShr_LIBRARY +# MDSplus_TdiShr_LIBRARY +# MDSplus_MdsLib_LIBRARY +# MDSplus_MdsIpShr_LIBRARY +# MDSplus_MdsObjectsCppShr_LIBRARY +# MDSplus_PYTHONPATH +# MDSplus_tditest_EXECUTABLE +# MDSplus_tdic_EXECUTABLE +# MDSplus_mdstcl_EXECUTABLE +# MDSplus_mdsdcl_EXECUTABLE +# MDSplus_setevent_EXECUTABLE +# MDSplus_wfevent_EXECUTABLE +# MDSplus_dwscope_EXECUTABLE +# MDSplus_traverser_EXECUTABLE +# MDSplus_jScope_EXECUTABLE +# MDSplus_jTraverser_EXECUTABLE +# MDSplus_jTraverser2_EXECUTABLE +# +# and the following imported targets +# +# MDSplus::Dynamic +# MDSplus::MdsShr +# MDSplus::TreeShr +# MDSplus::TdiShr +# MDSplus::MdsIpShr +# MDSplus::MdsLib +# MDSplus::MdsObjectsCppShr +# +# The following variables can be set as arguments +# +# MDSplus_ROOT +# +# If MDSplus_ROOT is not set, the following sources will be searched for MDSplus +# +# $ENV{MDSPLUS_DIR} +# file(READ /etc/.mdsplus_dir) +# /usr/local/mdsplus + +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(_MDSplus_lib_arch "lib32") + set(_MDSplus_bin_arch "bin32") +else() + set(_MDSplus_lib_arch "lib64") + set(_MDSplus_bin_arch "bin64") +endif() + +mark_as_advanced(_MDSplus_lib_arch) +mark_as_advanced(_MDSplus_bin_arch) + +if(DEFINED MDSplus_ROOT) + set(MDSPLUS_DIR "${MDSplus_ROOT}") +else() + if(DEFINED ENV{MDSPLUS_DIR}) + list(APPEND MDSPLUS_DIR $ENV{MDSPLUS_DIR}) + endif() + + if(EXISTS /etc/.mdsplus_dir) + file(READ /etc/.mdsplus_dir _MDSplus_etc_mdsplus_dir) + list(APPEND MDSPLUS_DIR ${_MDSplus_etc_mdsplus_dir}) + endif() + + if(MDSPLUS_DIR STREQUAL "") + set(MDSPLUS_DIR "/usr/local/mdsplus") + endif() +endif() + +find_path( + MDSplus_INCLUDE_DIRS + NAMES mdsplus/mdsconfig.h + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES include +) + +find_library( + MDSplus_MdsShr_LIBRARY + NAMES MdsShr + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_library( + MDSplus_TreeShr_LIBRARY + NAMES TreeShr + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_library( + MDSplus_TdiShr_LIBRARY + NAMES TdiShr + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_library( + MDSplus_MdsIpShr_LIBRARY + NAMES MdsIpShr + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_library( + MDSplus_MdsLib_LIBRARY + NAMES MdsLib + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_library( + MDSplus_MdsObjectsCppShr_LIBRARY + NAMES MdsObjectsCppShr + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES lib ${_MDSplus_lib_arch} +) + +find_path( + MDSplus_PYTHONPATH + NAMES MDSplus/__init__.py + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES python +) + +find_program( + MDSplus_tditest_EXECUTABLE + NAMES tditest + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_tdic_EXECUTABLE + NAMES tdic + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_mdstcl_EXECUTABLE + NAMES mdstcl + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_mdsdcl_EXECUTABLE + NAMES mdsdcl + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_setevent_EXECUTABLE + NAMES setevent + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_wfevent_EXECUTABLE + NAMES wfevent + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_dwscope_EXECUTABLE + NAMES dwscope + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_traverser_EXECUTABLE + NAMES traverser + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_jScope_EXECUTABLE + NAMES jScope + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_jTraverser_EXECUTABLE + NAMES jTraverser + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +find_program( + MDSplus_jTraverser2_EXECUTABLE + NAMES jTraverser2 + PATHS ${MDSPLUS_DIR} + PATH_SUFFIXES bin ${_MDSplus_bin_arch} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + MDSplus + HANDLE_COMPONENTS + REQUIRED_VARS + MDSPLUS_DIR + MDSplus_INCLUDE_DIRS + MDSplus_MdsShr_LIBRARY + MDSplus_TreeShr_LIBRARY + MDSplus_TdiShr_LIBRARY + MDSplus_MdsIpShr_LIBRARY + MDSplus_MdsLib_LIBRARY + MDSplus_MdsObjectsCppShr_LIBRARY + MDSplus_tditest_EXECUTABLE + MDSplus_tdic_EXECUTABLE + MDSplus_mdstcl_EXECUTABLE + MDSplus_mdsdcl_EXECUTABLE + MDSplus_setevent_EXECUTABLE + MDSplus_wfevent_EXECUTABLE +) + +if(MDSplus_FOUND) + + add_library(MDSplus::Dynamic INTERFACE IMPORTED) + + set_target_properties( + MDSplus::Dynamic + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + ) + + add_library(MDSplus::MdsShr INTERFACE IMPORTED) + + set_target_properties( + MDSplus::MdsShr + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_MdsShr_LIBRARY}" + ) + + add_library(MDSplus::TreeShr INTERFACE IMPORTED) + + set_target_properties( + MDSplus::TreeShr + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_TreeShr_LIBRARY};${MDSplus_MdsShr_LIBRARY}" + ) + + add_library(MDSplus::MdsIpShr INTERFACE IMPORTED) + + set_target_properties( + MDSplus::MdsIpShr + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_MdsIpShr_LIBRARY};${MDSplus_TdiShr_LIBRARY};${MDSplus_TreeShr_LIBRARY};${MDSplus_MdsShr_LIBRARY}" + ) + + add_library(MDSplus::TdiShr INTERFACE IMPORTED) + + set_target_properties( + MDSplus::TdiShr + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_TdiShr_LIBRARY};${MDSplus_TreeShr_LIBRARY};${MDSplus_MdsShr_LIBRARY}" + ) + + add_library(MDSplus::MdsLib INTERFACE IMPORTED) + + set_target_properties( + MDSplus::MdsLib + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_MdsLib_LIBRARY};${MDSplus_TdiShr_LIBRARY};${MDSplus_TreeShr_LIBRARY};${MDSplus_MdsShr_LIBRARY}" + ) + + add_library(MDSplus::MdsObjectsCppShr INTERFACE IMPORTED) + + set_target_properties( + MDSplus::MdsObjectsCppShr + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MDSplus_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${MDSplus_MdsObjectsCppShr_LIBRARY};${MDSplus_MdsIpShr_LIBRARY};${MDSplus_TdiShr_LIBRARY};${MDSplus_TreeShr_LIBRARY};${MDSplus_MdsShr_LIBRARY}" + ) + +endif() + +mark_as_advanced( + MDSPLUS_ROOT + MDSPLUS_DIR + MDSplus_INCLUDE_DIRS + MDSplus_MdsShr_LIBRARY + MDSplus_TreeShr_LIBRARY + MDSplus_TdiShr_LIBRARY + MDSplus_MdsLib_LIBRARY + MDSplus_MdsIpShr_LIBRARY + MDSplus_MdsObjectsCppShr_LIBRARY + MDSplus_PYTHONPATH + MDSplus_tditest_EXECUTABLE + MDSplus_tdic_EXECUTABLE + MDSplus_mdstcl_EXECUTABLE + MDSplus_mdsdcl_EXECUTABLE + MDSplus_setevent_EXECUTABLE + MDSplus_wfevent_EXECUTABLE + MDSplus_dwscope_EXECUTABLE + MDSplus_traverser_EXECUTABLE + MDSplus_jScope_EXECUTABLE + MDSplus_jTraverser_EXECUTABLE + MDSplus_jTraverser2_EXECUTABLE +) diff --git a/cmake/FindMotif.cmake b/cmake/FindMotif.cmake new file mode 100644 index 0000000000..a8ffb6e808 --- /dev/null +++ b/cmake/FindMotif.cmake @@ -0,0 +1,149 @@ +# FindMotif.cmake +# +# Finds Motif (Xm, Mrm, uil) and X11 (X11, Xt) +# +# This will define the following variables +# +# Motif_FOUND +# Motif_INCLUDE_DIRS +# Motif_Xm_INCLUDE_DIR +# Motif_Mrm_INCLUDE_DIR +# Motif_X11_INCLUDE_DIR +# Motif_Xt_INCLUDE_DIR +# Motif_LIBRARIES +# Motif_Xm_LIBRARY +# Motif_Mrm_LIBRARY +# Motif_X11_LIBRARY +# Motif_Xt_LIBRARY +# uil_EXECUTABLE +# +# and the following imported targets +# +# Motif::Motif +# +# The following variables can be set as arguments +# +# Motif_ROOT +# + +find_path( + Motif_Xm_INCLUDE_DIR + NAMES Xm/Xm.h + PATH_SUFFIXES + include +) + +find_path( + Motif_Mrm_INCLUDE_DIR + NAMES Mrm/MrmPublic.h + PATH_SUFFIXES + include +) + +find_path( + Motif_X11_INCLUDE_DIR + NAMES X11/X.h + PATH_SUFFIXES + include +) + +find_path( + Motif_Xt_INCLUDE_DIR + NAMES X11/Core.h + PATH_SUFFIXES + include +) + +find_library( + Motif_Xm_LIBRARY + NAMES Xm + PATH_SUFFIXES + lib +) + +find_library( + Motif_Mrm_LIBRARY + NAMES Mrm + PATH_SUFFIXES + lib +) + +find_library( + Motif_X11_LIBRARY + NAMES X11 + PATH_SUFFIXES + lib +) + +find_library( + Motif_Xt_LIBRARY + NAMES Xt + PATH_SUFFIXES + lib +) + +find_program( + uil_EXECUTABLE + NAMES uil + PATH_SUFFIXES + bin +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Motif + REQUIRED_VARS # The first one is displayed in the message + Motif_Xm_LIBRARY + Motif_Xm_INCLUDE_DIR + Motif_Mrm_INCLUDE_DIR + Motif_X11_INCLUDE_DIR + Motif_Xt_INCLUDE_DIR + Motif_Mrm_LIBRARY + Motif_X11_LIBRARY + Motif_Xt_LIBRARY + uil_EXECUTABLE +) + +if(Motif_FOUND) + + set(Motif_INCLUDE_DIRS + ${Motif_Xm_INCLUDE_DIR} + ${Motif_Mrm_INCLUDE_DIR} + ${Motif_X11_INCLUDE_DIR} + ${Motif_Xt_INCLUDE_DIR} + ) + + set(Motif_LIBRARIES + ${Motif_Xm_LIBRARY} + ${Motif_Mrm_LIBRARY} + ${Motif_X11_LIBRARY} + ${Motif_Xt_LIBRARY} + ) + + if(NOT TARGET Motif::Motif) + + add_library(Motif::Motif INTERFACE IMPORTED) + + set_target_properties( + Motif::Motif + PROPERTIES + INTERFACE_LINK_LIBRARIES "${Motif_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${Motif_INCLUDE_DIRS}" + ) + + endif() + +endif() + +mark_as_advanced( + Motif_ROOT + Motif_Xm_INCLUDE_DIR + Motif_Mrm_INCLUDE_DIR + Motif_X11_INCLUDE_DIR + Motif_Xt_INCLUDE_DIR + Motif_Xm_LIBRARY + Motif_Mrm_LIBRARY + Motif_X11_LIBRARY + Motif_Xt_LIBRARY + uil_EXECUTABLE +) \ No newline at end of file diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake new file mode 100644 index 0000000000..2a3a8fc31b --- /dev/null +++ b/cmake/FindReadline.cmake @@ -0,0 +1,90 @@ +# FindReadline.cmake +# +# Finds libreadline and libhistory +# +# This will define the following variables +# +# Readline_FOUND +# Readline_INCLUDE_DIRS +# Readline_LIBRARIES +# Readline_readline_LIBRARY +# Readline_history_LIBRARY +# +# and the following imported targets +# +# Readline::Readline +# +# The following variables can be set as arguments +# +# Readline_ROOT +# + +find_package(PkgConfig QUIET) + +pkg_check_modules(_Readline_PC QUIET readline) + +find_path( + Readline_INCLUDE_DIRS + NAMES readline/readline.h + PATHS + ${_Readline_PC_INCLUDE_DIRS} + PATH_SUFFIXES + include +) + +find_library( + Readline_readline_LIBRARY + NAMES readline + PATHS + ${_Readline_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +find_library( + Readline_history_LIBRARY + NAMES history + PATHS + ${_Readline_PC_LIBRARY_DIRS} + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Readline + REQUIRED_VARS + Readline_readline_LIBRARY + Readline_history_LIBRARY + Readline_INCLUDE_DIRS +) + +if(Readline_FOUND) + + set(Readline_LIBRARIES + ${Readline_readline_LIBRARY} + ${Readline_history_LIBRARY} + ) + + if(NOT TARGET Readline::Readline) + + add_library(Readline::Readline INTERFACE IMPORTED) + + set_target_properties( + Readline::Readline + PROPERTIES + INTERFACE_LINK_LIBRARIES "${Readline_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${Readline_INCLUDE_DIRS}" + ) + + endif() + +endif() + +mark_as_advanced( + Readline_ROOT + Readline_INCLUDE_DIRS + Readline_LIBRARIES + Readline_readline_LIBRARY + Readline_history_LIBRARY +) \ No newline at end of file diff --git a/cmake/FindSybase.cmake b/cmake/FindSybase.cmake new file mode 100644 index 0000000000..419441941c --- /dev/null +++ b/cmake/FindSybase.cmake @@ -0,0 +1,69 @@ +# FindSybase.cmake +# +# Finds Sybase (or mssql, or freetds) +# +# This will define the following variables +# +# Sybase_FOUND +# Sybase_INCLUDE_DIRS +# Sybase_LIBRARIES +# Sybase_COMPILE_DEFINITIONS +# +# and the following imported targets +# +# Sybase::Sybase +# +# The following variables can be set as arguments +# +# Sybase_ROOT +# + +set(Sybase_COMPILE_DEFINITIONS SYBASE) + +find_path( + Sybase_INCLUDE_DIRS + NAMES sybdb.h + PATH_SUFFIXES + include + include/freetds +) + +find_library( + Sybase_LIBRARIES + NAMES sybdb + PATH_SUFFIXES + lib +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Sybase + REQUIRED_VARS + Sybase_LIBRARIES + Sybase_INCLUDE_DIRS +) + +if(Sybase_FOUND) + + if(NOT TARGET Sybase::Sybase) + + add_library(Sybase::Sybase INTERFACE IMPORTED) + + set_target_properties( + Sybase::Sybase + PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "${Sybase_COMPILE_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${Sybase_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${Sybase_LIBRARIES}" + ) + + endif() + +endif() + +mark_as_advanced( + Sybase_ROOT + Sybase_COMPILE_DEFINITIONS + Sybase_INCLUDE_DIRS + Sybase_LIBRARIES +) \ No newline at end of file diff --git a/cmake/FindValgrind.cmake b/cmake/FindValgrind.cmake new file mode 100644 index 0000000000..2f7e6ff8fb --- /dev/null +++ b/cmake/FindValgrind.cmake @@ -0,0 +1,86 @@ +# FindValgrind.cmake +# +# Finds Valgrind and the available tools +# +# This will define the following variables +# +# Valgrind_FOUND +# Valgrind_memcheck_FOUND +# Valgrind_helgrind_FOUND +# Valgrind_drd_FOUND +# Valgrind_exp_sgcheck_FOUND +# Valgrind_TOOL_LIST +# Valgrind_EXECUTABLE +# Valgrind_VERSION +# +# The following variables can be set as arguments +# +# Valgrind_ROOT +# Valgrind_REQUESTED_TOOL_LIST +# + +find_program( + Valgrind_EXECUTABLE + NAMES valgrind + PATH_SUFFIXES + bin +) + +if(Valgrind_EXECUTABLE) + + if(NOT EXISTS Valgrind_VERSION) + + execute_process( + COMMAND ${Valgrind_EXECUTABLE} --version + OUTPUT_VARIABLE Valgrind_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Remove any text that is not part of the version, e.g. "valgrind-1.2.3" -> "1.2.3" + string(REGEX REPLACE "[\-a-zA-Z_]" "" Valgrind_VERSION "${Valgrind_VERSION}") + + endif() + + if(NOT EXISTS Valgrind_TOOL_LIST) + + foreach(_tool IN LISTS Valgrind_REQUESTED_TOOL_LIST) + + execute_process( + COMMAND ${Valgrind_EXECUTABLE} --tool=${_tool} --help + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE _result + ) + + if(_result EQUAL 0) + set(_found TRUE) + + list(APPEND Valgrind_TOOL_LIST ${_tool}) + else() + set(_found FALSE) + message(STATUS "Unable to find valgrind --tool ${_tool}") + endif() + + + string(REPLACE "-" "_" _tool_no_dash ${_tool}) + set(Valgrind_${_tool_no_dash}_FOUND ${_found}) + + endforeach() + + endif() + +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Valgrind + VERSION_VAR Valgrind_VERSION + REQUIRED_VARS # The first one is displayed in the message + Valgrind_EXECUTABLE +) + +mark_as_advanced( + Valgrind_ROOT + Valgrind_EXECUTABLE + Valgrind_TOOL_LIST +) diff --git a/cmake/MDSplusAddStaticCopy.cmake b/cmake/MDSplusAddStaticCopy.cmake new file mode 100644 index 0000000000..75a6123941 --- /dev/null +++ b/cmake/MDSplusAddStaticCopy.cmake @@ -0,0 +1,103 @@ +include_guard(GLOBAL) + +# +# mdsplus_add_static_copy( ) +# +# Create a static copy of a shared library, with all the same properties, +# and set ${out_static_target} to the name of the static library target. +# Note: If BUILD_SHARED_LIBS=OFF, then ${out_static_target} will be unset. +# +macro(mdsplus_add_static_copy _target _out_static_target) + + set(_static_target "${_target}-static") + + if(BUILD_SHARED_LIBS) + + set(${_out_static_target} ${_static_target}) + + add_library( + ${_static_target} STATIC + $ + ) + + set_target_properties( + ${_static_target} + PROPERTIES + OUTPUT_NAME "${_target}" + ) + + get_target_property( + _include_directories + ${_target} INTERFACE_INCLUDE_DIRECTORIES + ) + + if(_include_directories) + target_include_directories( + ${_static_target} + PUBLIC + "${_include_directories}" + ) + endif() + + get_target_property( + _compile_definitions + ${_target} INTERFACE_COMPILE_DEFINITIONS + ) + + if(_compile_definitions) + target_compile_definitions( + ${_static_target} + PUBLIC + ${_compile_definitions} + ) + endif() + + get_target_property( + _compile_options + ${_target} INTERFACE_COMPILE_OPTIONS + ) + + if(_compile_options) + target_compile_definitions( + ${_static_target} + PUBLIC + ${_compile_options} + ) + endif() + + get_target_property( + _link_libraries + ${_target} INTERFACE_LINK_LIBRARIES + ) + + if(_link_libraries) + target_link_libraries( + ${_static_target} + PUBLIC + ${_link_libraries} + ) + endif() + + get_target_property( + _link_options + ${_target} INTERFACE_LINK_OPTIONS + ) + + if(_link_options) + target_link_options( + ${_static_target} + PUBLIC + ${_link_options} + ) + endif() + + else() + + unset(${_out_static_target}) + + # Add an alias for things that link against the static target directly + add_library(${_static_target} ALIAS ${_target}) + + endif() + +endmacro() \ No newline at end of file diff --git a/cmake/MDSplusAddTest.cmake b/cmake/MDSplusAddTest.cmake new file mode 100644 index 0000000000..dcf95c0e88 --- /dev/null +++ b/cmake/MDSplusAddTest.cmake @@ -0,0 +1,287 @@ +include_guard(GLOBAL) + +set(MDSPLUS_TEST_INDEX 0 CACHE STRING "" FORCE) + +# +# mdsplus_add_test(NAME +# COMMAND [...]) +# [WORKING_DIRECTORY ] +# [ENVIRONMENT_MODIFICATIONS ] +# [NO_VALGRIND] +# [NO_WINE]) +# +# Call add_test() and set_tests_properties() to configure all of the test's properties. +# +# If ENABLE_VALGRIND=ON and NO_VALGRIND is not set, then another test will be added +# for each tool in Valgrind_TOOL_LIST. +# +# If GENERATE_VSCODE_LAUNCH_JSON=ON, then deploy/add-launch-target.py will be called +# for each test as well. +# +# https://cmake.org/cmake/help/latest/command/add_test.html +# https://cmake.org/cmake/help/latest/prop_test/ENVIRONMENT_MODIFICATION.html +# +if(GENERATE_VSCODE_LAUNCH_JSON AND NOT TARGET generate-vscode-launch-json) + add_custom_target(generate-vscode-launch-json) + set(LAST_VSCODE_LAUNCH_JSON_TARGET "generate-vscode-launch-json" CACHE INTERNAL "" FORCE) +endif() + +set(MDSPLUS_TEST_ENV_MODS + # Used to find the rest of MDSplus + "MDSPLUS_DIR=set:${CMAKE_SOURCE_DIR}" + "MDSPLUS_LIBRARY_PATH=set:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" + + # Used to search for TDI and Python scripts, and to add TDI drivers + "MDS_PATH=set:${CMAKE_SOURCE_DIR}/tdi" + + # Used to run or load Python + "PYTHON=set:${PYTHON}" + "PyLib=set:${PyLib}" + + # Needed for `import MDSplus` in Python + "PYTHONPATH=set:${CMAKE_SOURCE_DIR}/python" + + # Needed to add Python drivers + "MDS_PYDEVICE_PATH=set:${CMAKE_SOURCE_DIR}/pydevices" + + # Needed to run MDSplus executables + "PATH=path_list_prepend:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + + # Several tests make use of the default trees + "main_path=set:${CMAKE_SOURCE_DIR}/trees" + "subtree_path=set:${CMAKE_SOURCE_DIR}/trees/subtree" + + # Write all new tree files into the current directory + "default_tree_path=set:." +) + +if(WIN32) + + list(APPEND MDSPLUS_TEST_ENV_MODS + "OS=set:windows" # for do_tditests.sh + ) + + if(TEST_WITH_WINE) + # These are used even if NO_WINE is set for do_tditests.sh + list(APPEND MDSPLUS_TEST_ENV_MODS + "WINEDEBUG=set:-all" + "WINEARCH=set:${WINEARCH}" + "WINEPREFIX=set:${WINEPREFIX}" + "WINEPATH=cmake_list_prepend:${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + # https://askubuntu.com/questions/323437/how-to-prevent-wine-from-adding-file-associations + "WINEDLLOVERRIDES=set:winemenubuilder.exe=d,explorer.exe=d" + + # Don't inherit the system python environment + "PYTHONHOME=unset:" + ) + endif() + +else() + + # Linux searches $LD_LIBRARY_PATH for loading .so's + # This is set for Apple as well for backwards compatibility + list(APPEND MDSPLUS_TEST_ENV_MODS + "LD_LIBRARY_PATH=path_list_prepend:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" + + ${SANITIZER_ENV_MODS} + + # Sometimes required by the sanitizers + "LD_PRELOAD=set:${LD_PRELOAD}" + ) + + if(APPLE) + # Apple searches $DYLD_LIBRARY_PATH for loading .dylib's + list(APPEND MDSPLUS_TEST_ENV_MODS + "DYLD_LIBRARY_PATH=path_list_prepend:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" + ) + endif() + +endif() + +macro(_mdsplus_add_vscode_launch_target _target _command _env_mods _cwd) + string(REPLACE "/" "-" _vscode_launch_target "generate-vscode-launch-json-${_target}") + + message(STATUS "Adding generate-vscode-launch-json target for ${_target}") + + add_custom_target( + "${_vscode_launch_target}" + COMMENT "Adding ${_target} to .vscode/launch.json" + COMMAND ${Python_EXECUTABLE} deploy/add-launch-target.py + --name "${_target}" + --command "\"${_command}\"" + --environment "\"${_env_mods}\"" + --cwd "${_cwd}" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + + # We chain the dependencies to force them to run in serial + add_dependencies("${LAST_VSCODE_LAUNCH_JSON_TARGET}" "${_vscode_launch_target}") + set(LAST_VSCODE_LAUNCH_JSON_TARGET "${_vscode_launch_target}" CACHE INTERNAL "" FORCE) +endmacro() + +# TODO: Ensure they use the right environment +# Useful tools for debugging that shouldn't be added as actual tests +if(GENERATE_VSCODE_LAUNCH_JSON) + _mdsplus_add_vscode_launch_target("mdstcl" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mdsdcl;-prep;set command tcl_commands -history=.tcl" "${MDSPLUS_TEST_ENV_MODS}" ${CMAKE_BINARY_DIR}) + _mdsplus_add_vscode_launch_target("python" "${Python_EXECUTABLE}" "${MDSPLUS_TEST_ENV_MODS}" ${CMAKE_BINARY_DIR}) + _mdsplus_add_vscode_launch_target("tditest" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tditest" "${MDSPLUS_TEST_ENV_MODS}" ${CMAKE_BINARY_DIR}) + _mdsplus_add_vscode_launch_target("tdic" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tdic" "${MDSPLUS_TEST_ENV_MODS}" ${CMAKE_BINARY_DIR}) + _mdsplus_add_vscode_launch_target("mdsip-8888" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mdsip;-p;8888;-s;-h;${CMAKE_SOURCE_DIR}/mdstcpip/mdsip.hosts" "${MDSPLUS_TEST_ENV_MODS}" ${CMAKE_BINARY_DIR}) +endif() + +function(mdsplus_add_test) + + cmake_parse_arguments( + PARSE_ARGV 0 ARGS + # Booleans + "NO_VALGRIND;NO_WINE" + # Single-Value + "NAME;WORKING_DIRECTORY;TEST_LIST_VARIABLE" + # Multi-Value + "COMMAND;ENVIRONMENT_MODIFICATION" + ) + + if(NOT DEFINED ARGS_WORKING_DIRECTORY) + set(ARGS_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + endif() + + set(_env_mods "${MDSPLUS_TEST_ENV_MODS}") + + list(APPEND _env_mods + # Some tests define their own TDI functions + "MDS_PATH=cmake_list_prepend:${CMAKE_CURRENT_SOURCE_DIR}" + ) + + if(WIN32 AND TEST_WITH_WINE) + if(NOT ARGS_NO_WINE) + list(PREPEND ARGS_COMMAND ${wine_EXECUTABLE}) + endif() + endif() + + set(_test_port_offset 0) + if(NOT TEST_PORT_OFFSET STREQUAL "OFF") + set(_test_port_offset "${TEST_PORT_OFFSET}") + endif() + + set(_index ${MDSPLUS_TEST_INDEX}) + math(EXPR _event_port "4000 + ${_index} + ${_test_port_offset}") + + list(APPEND _env_mods ${ARGS_ENVIRONMENT_MODIFICATION}) + + set(_base_env_mods + ${_env_mods} + "TEST_INDEX=set:${_index}" + "TEST_PORT_OFFSET=set:${_test_port_offset}" + "mdsevent_port=set:${_event_port}" + "MDSIP_CLIENT_LOCAL_LOGFILE=set:${CMAKE_CURRENT_BINARY_DIR}/mdsip-local-${ARGS_NAME}-${_index}.log" + ) + + file(RELATIVE_PATH _path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + string(REPLACE "\\" "/" _path "${_path}") + + set(_target "${_path}/${ARGS_NAME}") + + set(_target_list "${_target}") + + add_test( + NAME ${_target} + COMMAND ${ARGS_COMMAND} + WORKING_DIRECTORY ${ARGS_WORKING_DIRECTORY} + ) + + set_tests_properties( + ${_target} + PROPERTIES + ENVIRONMENT_MODIFICATION "${_base_env_mods}" + FAIL_REGULAR_EXPRESSION "FAILED" + ) + + math(EXPR _index "${_index} + 1") + + if(GENERATE_VSCODE_LAUNCH_JSON) + _mdsplus_add_vscode_launch_target(${_target} "${ARGS_COMMAND}" "${_base_env_mods}" ${ARGS_WORKING_DIRECTORY}) + endif() + + if(ENABLE_VALGRIND AND NOT ARGS_NO_VALGRIND) + + if(NOT TEST_PORT_OFFSET STREQUAL "OFF") + message(DEBUG "It is not recommended to use TEST_PORT_OFFSET with valgrind tools, the port ranges can easily conflict") + endif() + + set(_valgrind_flags ${Valgrind_FLAGS}) + foreach(_supp IN LISTS Valgrind_SUPPRESSION_FILES) + list(APPEND _valgrind_flags "--suppressions=${_supp}") + endforeach() + + # Each variant of tests gets a unique port range + math(EXPR _test_port_offset "${_test_port_offset} + 1000") + + foreach(_tool IN LISTS Valgrind_TOOL_LIST) + set(_target_tool "${_target}-${_tool}") + list(APPEND _target_list "${_target_tool}") + + string(REPLACE "-" "_" _tool_no_dash ${_tool}) + + file(MAKE_DIRECTORY ${ARGS_WORKING_DIRECTORY}/${_tool}) + + add_test( + NAME "${_target_tool}" + COMMAND ${Valgrind_EXECUTABLE} --tool=${_tool} --quiet ${_valgrind_flags} ${Valgrind_${_tool_no_dash}_FLAGS} ${ARGS_COMMAND} + WORKING_DIRECTORY ${ARGS_WORKING_DIRECTORY}/${_tool} + ) + + math(EXPR _event_port "4000 + ${_index} + ${_test_port_offset}") + + set(_valgrind_env_mods + ${_env_mods} + "TEST_INDEX=set:${_index}" + "TEST_PORT_OFFSET=set:${_test_port_offset}" + "mdsevent_port=set:${_event_port}" + "MDSIP_CLIENT_LOCAL_LOGFILE=set:${CMAKE_CURRENT_BINARY_DIR}/mdsip-local-${ARGS_NAME}-${_index}.log" + ) + + set_tests_properties( + "${_target_tool}" + PROPERTIES + ENVIRONMENT_MODIFICATION "${_valgrind_env_mods}" + FAIL_REGULAR_EXPRESSION "FAILED" + ) + + # valgrind is a shell script, so adding it as a launch target causes some issues + + math(EXPR _index "${_index} + 1") + endforeach() + + endif() + + set(MDSPLUS_TEST_INDEX "${_index}" CACHE STRING "" FORCE) + + if (DEFINED ARGS_TEST_LIST_VARIABLE) + set(${ARGS_TEST_LIST_VARIABLE} "${_target_list}" PARENT_SCOPE) + endif() + +endfunction() + +if(NOT WIN32) + set(_test_env_filename "${CMAKE_BINARY_DIR}/test-env.sh") + file(WRITE ${_test_env_filename} + "#!/bin/bash\n" + "export MDSPLUS_DIR=${CMAKE_SOURCE_DIR}\n" + "export MDS_PATH=${CMAKE_SOURCE_DIR}/tdi\n" + "export PyLib=${Python_LIBRARIES}\n" + "export PYTHONPATH=${CMAKE_SOURCE_DIR}/python\n" + "export MDS_PYDEVICE_PATH=${CMAKE_SOURCE_DIR}/pydevices\n" + "export PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}:$PATH\n" + "export LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\n" + "export main_path=${CMAKE_SOURCE_DIR}/trees\n" + "export subtree_path=${CMAKE_SOURCE_DIR}/trees/subtree\n" + "/bin/bash --init-file <(echo \"PS1='MDSplus Test $ '\")\n" + ) + # TODO: Improve + file(CHMOD ${_test_env_filename} + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) +endif() \ No newline at end of file diff --git a/cmake/MDSplusCheckAddFlags.cmake b/cmake/MDSplusCheckAddFlags.cmake new file mode 100644 index 0000000000..d17375b8f3 --- /dev/null +++ b/cmake/MDSplusCheckAddFlags.cmake @@ -0,0 +1,115 @@ +include_guard(GLOBAL) + +include(CheckCompilerFlag) + +# +# mdsplus_check_add_flags( +# [COMPILER ] +# [LINKER ] +# [LANGUAGES ]) +# +# Check if the COMPILER/LINKER flags are supported for the given LANGUAGES, and add them if they are. +# The compiler flags will be added to CMAKE_${LANG}_FLAGS for the supported languages, and the linker flags will be passed +# to add_link_options() if all languages pass their checks. +# LANGUAGES will default to "C;CXX;Fortran" if not specified. +# +function(mdsplus_check_add_flags) + + # The ARGS is a prefix to all parsed argument variables + cmake_parse_arguments( + PARSE_ARGV 0 ARGS + # Booleans + "" + # Single-Value + "" + # Multi-Value + "COMPILER;LINKER;LANGUAGES" + ) + + if(NOT DEFINED ARGS_LANGUAGES) + set(ARGS_LANGUAGES C CXX Fortran) + endif() + + set(_all_passed TRUE) + foreach(_lang IN ITEMS ${ARGS_LANGUAGES}) + + # This will be the name of a cache variable that will persist between configures, so it needs to + # be unique and consistent, computed from the requested flags + set(_variable_name "MDSPLUS_CHECK_ADD_FLAGS_${_lang}_${ARGS_COMPILER}_${ARGS_LINKER}") + string(REPLACE ";" "_" _variable_name "${_variable_name}") + string(REPLACE "-" "_" _variable_name "${_variable_name}") + string(REPLACE "/" "_" _variable_name "${_variable_name}") + string(REPLACE "=" "_" _variable_name "${_variable_name}") + + if(NOT DEFINED ${_variable_name}) + message(CHECK_START "Checking if flags are supported for ${_lang}") + + if(DEFINED ARGS_COMPILER) + + string(REPLACE ";" " " _compiler_flags_message "${ARGS_COMPILER}") + + if(_lang STREQUAL "C") + set(_compiler_flags_message "CFLAGS=${_compiler_flags_message}") + elseif(_lang STREQUAL "CXX") + set(_compiler_flags_message "CXXFLAGS=${_compiler_flags_message}") + elseif(_lang STREQUAL "Fortran") + set(_compiler_flags_message "FCFLAGS=${_compiler_flags_message}") + endif() + + message(STATUS " ${_compiler_flags_message}") + + endif() + + if(DEFINED ARGS_LINKER) + + string(REPLACE ";" " " _linker_flags_message "${ARGS_LINKER}") + set(_linker_flags_message "LDFLAGS=${_linker_flags_message}") + + message(STATUS " ${_linker_flags_message}") + + endif() + + # Remove the current flags so they don't interfere with the test + set(_saved_flags "${CMAKE_${_lang}_FLAGS}") + unset(CMAKE_${_lang}_FLAGS) + + # Disable the default messaging to replace it with our own + set(CMAKE_REQUIRED_QUIET ON) + + # In order to check more than one flag at a time, we use these and set to "" + set(CMAKE_REQUIRED_FLAGS ${ARGS_COMPILER}) + set(CMAKE_REQUIRED_LINK_OPTIONS ${ARGS_LINKER}) + + check_compiler_flag(${_lang} "" ${_variable_name}) + set(_result ${${_variable_name}}) + + unset(CMAKE_REQUIRED_FLAGS) + unset(CMAKE_REQUIRED_LINK_OPTIONS) + + set(CMAKE_REQUIRED_QUIET OFF) + + set(CMAKE_${_lang}_FLAGS "${_saved_flags}") + + if(${_result}) + message(CHECK_PASS "Success") + else() + message(CHECK_FAIL "Failed") + endif() + + endif() + + if(${_variable_name}) + if(DEFINED ARGS_COMPILER) + set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${ARGS_COMPILER}" PARENT_SCOPE) + endif() + else() + set(_all_passed FALSE) + endif() + + endforeach() + + if(DEFINED ARGS_LINKER AND ${_all_passed}) + add_link_options(${ARGS_LINKER}) + endif() + +endfunction() \ No newline at end of file diff --git a/cmake/MDSplusGenerateFiles.cmake b/cmake/MDSplusGenerateFiles.cmake new file mode 100644 index 0000000000..a90b5687b3 --- /dev/null +++ b/cmake/MDSplusGenerateFiles.cmake @@ -0,0 +1,46 @@ +include_guard(GLOBAL) + +# +# mdsplus_generate_files(COMMAND [...]) +# GENERATED_FILES ) +# +# Check if any of the GENERATED_FILES are missing, and run COMMAND to generate them if they are. +# +function(mdsplus_generate_files) + + cmake_parse_arguments( + PARSE_ARGV 0 ARGS + # Booleans + "" + # Single-Value + "" + # Multi-Value + "COMMAND;GENERATED_FILES" + ) + + string(REPLACE ";" " " _print_command "${ARGS_COMMAND}") + + # Check to see if we already have all the files generated + set(_will_run_command OFF) + foreach(_file IN LISTS ARGS_GENERATED_FILES) + if(NOT EXISTS ${CMAKE_SOURCE_DIR}/${_file}) + message("Missing '${_file}', will run ${_print_command}") + set(_will_run_command TRUE) + endif() + endforeach() + + # If not, generate them + if(_will_run_command) + message(STATUS "Running ${_print_command}") + execute_process( + COMMAND ${ARGS_COMMAND} + RESULT_VARIABLE _result + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + + if(NOT _result EQUAL 0) + message(FATAL_ERROR "Failed to run ${_print_command}") + endif() + endif() + +endfunction() diff --git a/cmake/MDSplusGetAllTargets.cmake b/cmake/MDSplusGetAllTargets.cmake new file mode 100644 index 0000000000..a790a41aca --- /dev/null +++ b/cmake/MDSplusGetAllTargets.cmake @@ -0,0 +1,24 @@ +include_guard(GLOBAL) + +function(mdsplus_get_all_targets _output_list_variable) + + set(_all_project_dirs "") + get_property(_stack DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY SUBDIRECTORIES) + while(_stack) + list(POP_BACK _stack _dir) + list(APPEND _all_project_dirs ${_dir}) + + get_property(_subdirs DIRECTORY ${_dir} PROPERTY SUBDIRECTORIES) + if(_subdirs) + list(APPEND stack ${_subdirs}) + endif() + endwhile() + + foreach(_dir ${_all_project_dirs}) + get_property(_dir_target_list DIRECTORY ${_dir} PROPERTY BUILDSYSTEM_TARGETS) + list(APPEND _target_list ${_dir_target_list}) + endforeach() + + set(${_output_list_variable} ${_target_list} PARENT_SCOPE) + +endfunction() \ No newline at end of file diff --git a/cmake/MDSplusGit.cmake b/cmake/MDSplusGit.cmake new file mode 100644 index 0000000000..0fbe3becff --- /dev/null +++ b/cmake/MDSplusGit.cmake @@ -0,0 +1,21 @@ +include_guard(GLOBAL) + +find_package(Git) + +if(GIT_FOUND) + + # Convenience macro for all the git queries we need to make + macro(mdsplus_git _output_variable) # additional arguments are in ${ARGN} + execute_process( + COMMAND "${GIT_EXECUTABLE}" ${ARGN} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE _result + OUTPUT_VARIABLE ${_output_variable} + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT _result EQUAL 0) + SET(${_output_variable} "NOTFOUND") # NOTFOUND is CMake's version of NULL + endif() + endmacro() + +endif() diff --git a/cmake/MDSplusOption.cmake b/cmake/MDSplusOption.cmake new file mode 100644 index 0000000000..7cf4a0e9dd --- /dev/null +++ b/cmake/MDSplusOption.cmake @@ -0,0 +1,95 @@ +include_guard(GLOBAL) + +# The BUILD_TESTING option is created by include(CTest), so we just add it to the list manually +set(MDSPLUS_OPTION_LIST "BUILD_TESTING") + +# +# mdsplus_option( +# [DEFAULT ] +# [OPTIONS