diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 713a117ff..88ef8b462 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,192 @@ jobs: needs: [style] uses: ./.github/workflows/_test-macos.yml + cmake-configure: + name: CMake Configure (${{ matrix.cfg.os }} ${{ matrix.cfg.tag }}) + needs: [style] + # TODO: Remove always() once style enforcement is stable — ideally builds only run on clean style. + if: always() + runs-on: ubuntu-latest + container: docker://${{ matrix.cfg.image }}:${{ matrix.cfg.tag }} + strategy: + fail-fast: false + matrix: + cfg: + - { os: ubuntu, tag: 24.04, arch: debian, image: ubuntu } + - { os: ubuntu, tag: 26.04, arch: debian, image: ubuntu } + - { os: rockylinux, tag: 9, arch: rhel, image: rockylinux/rockylinux } + include: + - cfg: {} + deps: >- + bison + clang + flex + git + llvm + make + maven + cmake + swig + zip + gdb + conf_pkg: echo package manager already configured + enable_repo: "" + install_cmd: install -y + + #-------- Debian-based Dependencies ---------------- + - cfg: { arch: debian } + pkg_mgr: apt-get + conf_pkg: apt-get update + arch_deps: >- + curl + g++ + libx11-dev + libxml2-dev + libxt-dev + libmotif-common + libmotif-dev + zlib1g-dev + llvm-dev + libclang-dev + libudunits2-dev + libgtest-dev + libgmock-dev + libgsl-dev + libhdf5-dev + default-jdk + python3-dev + python3-pip + python3-venv + python3-yaml + python3-psutil + + #-------- RHEL-based Dependencies (all versions) ---------------- + - cfg: { arch: rhel } + pkg_mgr: dnf + conf_pkg: | + dnf -y install epel-release + dnf -y update + dnf install -y 'dnf-command(config-manager)' + arch_deps: >- + clang-devel + diffutils + gcc + gcc-c++ + gtest-devel + gmock-devel + gsl-devel + hdf5-devel + java-21-openjdk-devel + libxml2-devel + llvm-devel + llvm-static + ncurses-devel + openmotif + openmotif-devel + perl + perl-Digest-MD5 + udunits2 + udunits2-devel + which + zlib-devel + python3-devel + python3-pyyaml + python3-psutil + + #-------- RHEL 9: gtest lives in crb ---------------- + - cfg: { arch: rhel, tag: 9 } + enable_repo: dnf config-manager --enable crb + + steps: + - name: Set noninteractive mode + run: echo "DEBIAN_FRONTEND=noninteractive" >> "$GITHUB_ENV" + if: matrix.cfg.arch == 'debian' + - name: Update Package Manager + run: | + ${{ matrix.conf_pkg }} + ${{ matrix.enable_repo }} + - name: Install Dependencies + run: > + ${{ matrix.pkg_mgr }} + ${{ matrix.install_cmd }} + ${{ matrix.deps }} + ${{ matrix.arch_deps }} + - name: Checkout repository + uses: actions/checkout@v6 + # A dedicated step: GITHUB_ENV writes only take effect in *subsequent* + # steps, so setting JAVA_HOME inline in the same run block as a script + # would leave that script itself without it. + - name: Set JAVA_HOME + run: echo "JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))" >> "$GITHUB_ENV" + - name: Compare autoconf vs cmake config_user.mk (Phase 1) + run: test/build_config/compare_config_user.sh + - name: CMake build + archive parity vs make (Phase 2) + run: test/build_config/compare_archives.sh + - name: CMake install + CTest (Phase 3) + run: | + NPROC="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" + # Three-step io_src bootstrap: a nonexistent-at-first-configure + # generated list does not wire itself into CMAKE_CONFIGURE_DEPENDS + # (see cmake/TrickICG.cmake) — the first `trick_io_src_gen` build + # writes it, then a reconfigure picks it up before the real build. + cmake -S . -B build + cmake --build build --target trick-ICG trick_io_src_gen -j"$NPROC" + cmake -S . -B build + cmake --build build -j"$NPROC" + # Stage a runnable TRICK_HOME (build/stage) — the stage_install + # fixture in cmake/TrickTest.cmake also does this, but doing it + # explicitly here surfaces install errors directly. + cmake --build build --target stage -j"$NPROC" + ctest --test-dir build --output-on-failure -L '^(unit|sims)$' + + cmake-configure-macos: + name: CMake Configure (macOS) + needs: [style] + # TODO: Remove always() once style enforcement is stable — ideally builds only run on clean style. + if: always() + runs-on: macos-26 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Install dependencies + run: | + brew update || true + brew upgrade || true + brew install --cask xquartz + brew install udunits openmotif maven googletest gsl hdf5 + brew install swig llvm + # sims (LABEL sims, exercised by the Phase 3 step below) drives + # trickops.py, which needs PyYAML/psutil — it's the only sims test now + # (replaced the two-sim smoke subset), so installing these is no longer + # optional for this job. Installed into the same Python3 `cmake` resolves + # at configure time (find_package(Python3 ...) in TrickTest.cmake) and + # bakes as an absolute path into the generated ctest command — a venv's + # activate script in a later step would not reach that baked-in path, so + # this installs directly rather than isolating in a venv like the + # autotools test-macos job above does. + - name: Install trickops Python dependencies + run: pip3 install --break-system-packages -r share/trick/trickops/requirements.txt + - name: Compare autoconf vs cmake config_user.mk (Phase 1) + run: test/build_config/compare_config_user.sh + - name: CMake build + archive parity vs make (Phase 2) + run: test/build_config/compare_archives.sh + - name: CMake install + CTest (Phase 3) + run: | + NPROC="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" + # Three-step io_src bootstrap: a nonexistent-at-first-configure + # generated list does not wire itself into CMAKE_CONFIGURE_DEPENDS + # (see cmake/TrickICG.cmake) — the first `trick_io_src_gen` build + # writes it, then a reconfigure picks it up before the real build. + cmake -S . -B build + cmake --build build --target trick-ICG trick_io_src_gen -j"$NPROC" + cmake -S . -B build + cmake --build build -j"$NPROC" + # Stage a runnable TRICK_HOME (build/stage) — the stage_install + # fixture in cmake/TrickTest.cmake also does this, but doing it + # explicitly here surfaces install errors directly. + cmake --build build --target stage -j"$NPROC" + ctest --test-dir build --output-on-failure -L '^(unit|sims)$' + trickops: needs: [style] uses: ./.github/workflows/_trickops.yml diff --git a/.gitignore b/.gitignore index 9fff8097e..2f4f910ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Build artifacts +*.o object_* io_src swig @@ -19,8 +20,24 @@ lib_Darwin_* *.gcno coverage.info gmon.out -compile_commands.json Makefile_jsc_dirs +.extracted +__.SYMDEF + +# CMake +build*/ +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +CMakeUserPresets.json # Autoconf / configure config.status* @@ -56,7 +73,6 @@ share/trick/makefiles/config_user.mk # Editor / OS *~ *.swp -*.dox .DS_Store .vscode/ .cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 73921ff7e..efa6a9b34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,425 +1,199 @@ -cmake_minimum_required(VERSION 3.1) - -# trick is a C/C++ project, but we have some macOS -# configuration to do before CMake searches for compilers -project(trick NONE) -set(TRICK_MAJOR 25) -set(TRICK_MINOR 1) -set(TRICK_TINY 1) -# set TRICK_PRERELEASE TO EMPTY STRING "" ON RELEASE -set(TRICK_PRERELEASE "-beta") - -# On macOS Mojave and Catalina, the compilers in /usr/bin -# are the ones that include the correct C standard library system headers -if(CMAKE_SYSTEM_NAME MATCHES Darwin) - if ( (NOT DEFINED CMAKE_C_COMPILER) AND (NOT DEFINED ENV{CC}) AND (EXISTS /usr/bin/cc) ) - set(CMAKE_C_COMPILER /usr/bin/cc) +# Range form: 3.20 is the supported floor (oldest distro CMake we target); the +# upper bound opts every policy introduced through 4.3 into its NEW behavior +# when built with a CMake that new, without raising the floor contributors need. +cmake_minimum_required(VERSION 3.20...4.3) + +# Version lives in share/trick/trick_ver.txt — the single source of truth +# also read by bin/trick-version at sim-build time (Makefile.common:28-30). +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/share/trick/trick_ver.txt TR_VER_TXT) +string(REGEX MATCH "current_version *= *\"([0-9]+)\\.([0-9]+)\\.([0-9]+)([^\"]*)\"" _ "${TR_VER_TXT}") +set(TRICK_MAJOR ${CMAKE_MATCH_1}) +set(TRICK_MINOR ${CMAKE_MATCH_2}) +set(TRICK_TINY ${CMAKE_MATCH_3}) +set(TRICK_PRERELEASE ${CMAKE_MATCH_4}) + +# Mirror AC_PROG_CC/AC_PROG_CXX's default search order (gcc/cc, g++/c++) so +# CMAKE_C_COMPILER/CMAKE_CXX_COMPILER matches what ./configure would pick. +# Compiler selection must happen before project() enables the languages; it +# still honors the CC/CXX environment variables exactly like autoconf does. +if(NOT DEFINED ENV{CC} AND NOT CMAKE_C_COMPILER) + find_program(TR_C_COMPILER NAMES gcc cc) + if(TR_C_COMPILER) + set(CMAKE_C_COMPILER "${TR_C_COMPILER}") endif() - if ( (NOT DEFINED CMAKE_CXX_COMPILER) AND (NOT DEFINED ENV{CXX}) AND (EXISTS /usr/bin/c++) ) - set(CMAKE_CXX_COMPILER /usr/bin/c++) +endif() +if(NOT DEFINED ENV{CXX} AND NOT CMAKE_CXX_COMPILER) + find_program(TR_CXX_COMPILER NAMES g++ c++) + if(TR_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${TR_CXX_COMPILER}") endif() endif() +project(trick VERSION ${TRICK_MAJOR}.${TRICK_MINOR}.${TRICK_TINY} LANGUAGES C CXX) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +# ────────────────────────────────────────────────────────────────────────── +# Options (Part C, Phase 1, step 1 of CMAKE_MIGRATION_PLAN.md) +# ────────────────────────────────────────────────────────────────────────── +option(TRICK_FORCE_32BIT "Force Trick and sims to compile 32bit" OFF) +option(TRICK_OFFLINE "Compile Trick in offline mode (requires trick-offline/ in the source tree)" OFF) +option(TRICK_USE_JAVA "Build the Trick Java GUIs" ON) +option(TRICK_BUILD_DP "Build the X11/Motif data_products tools" ON) +set(TRICK_CIVETWEB_HOME "" CACHE PATH "CivetWeb root directory (empty = auto-detect/disabled)") +set(HDF5_HOME "" CACHE PATH "HDF5 root directory (empty = auto-detect)") +set(GSL_HOME "" CACHE PATH "GSL root directory (empty = auto-detect)") +set(GTEST_HOME "" CACHE PATH "GoogleTest root directory (empty = auto-detect)") +set(LLVM_HOME "" CACHE PATH "LLVM root directory (empty = auto-detect)") +set(UDUNITS_HOME "" CACHE PATH "UDUnits2 root directory (empty = auto-detect)") +set(PYTHON_VERSION "" CACHE STRING "Suffix for python search, e.g. 3 looks for python3") + +# -m32 propagates through the trick_build_flags INTERFACE target below, NOT +# directory-wide: Makefile.common:119-122 only puts -m32 on TRICK_ICGFLAGS/ +# TRICK_SYSTEM_CXXFLAGS/TRICK_SYSTEM_LDFLAGS (flags for sim/library code), +# never on the trick-ICG tool's own compile — a 32-bit ICG can't link the +# 64-bit LLVM archives — and data_products' own -m32 gate +# (TRICK_DP_FORCE_32BIT) is dead upstream, so it never builds 32-bit either. +if(TRICK_FORCE_32BIT) + set(TRICK_FORCE_32BIT_MK 1) +else() + set(TRICK_FORCE_32BIT_MK 0) +endif() -enable_language(C) -enable_language(CXX) - -#set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(TRICK_FORCE_32BIT OFF CACHE BOOL "Set Trick to compile in 32bit mode") -#set(USE_JAVA ON CACHE BOOL "Use java") -set(USE_ER7_UTILS ON CACHE BOOL "Use er7_utils") -set(UDUNITS2_ROOT "" CACHE STRING "UDUNITS home directory") -set(TRICK_MONGOOSE "0" CACHE STRING "Enable webserver") - -#message("UDUNITS2_ROOT = ${UDUNITS2_ROOT}") - -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -if(EXISTS "/etc/redhat-release") - if(TRICK_FORCE_32BIT) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - else() - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib64) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib64) +if(TRICK_OFFLINE) + if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/trick-offline") + message(FATAL_ERROR "Offline mode requires an uncompressed directory named \"trick-offline\" in TRICK_HOME") endif() + set(TRICK_OFFLINE_MK 1) else() - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(TRICK_OFFLINE_MK 0) endif() -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) -include(UseJava) -find_package(Java REQUIRED) -find_package(Maven REQUIRED) -find_package(BISON REQUIRED) -find_package(FLEX REQUIRED) -find_package(LLVM 3.4 REQUIRED) -find_package(Perl REQUIRED) -find_package(PythonInterp REQUIRED) -find_package(PythonLibs REQUIRED) -find_package(SWIG REQUIRED) -find_package(Tee REQUIRED) -find_package(Threads REQUIRED) -find_package(UDUNITS2 REQUIRED) -find_package(LibXml2 REQUIRED) -find_package(HDF5) -find_package(GSL) - -find_package(X11) -find_package(Motif) - -add_definitions( -DTRICK_VER=${TRICK_MAJOR} ) +# ────────────────────────────────────────────────────────────────────────── +# Detection (no compilation happens in Phase 1 — see A2/D3 in the plan: sims +# consume config_user.mk via the make flow, which is the real product here) +# ────────────────────────────────────────────────────────────────────────── +include(TrickPrograms) +include(FindLLVMClang) +include(TrickClangLibs) +include(TrickPython) +include(FindUDUNITS2) +include(TrickGTest) + +# ────────────────────────────────────────────────────────────────────────── +# config_user.mk (D4: golden-file-tested parity with autoconf's output) +# ────────────────────────────────────────────────────────────────────────── +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/share/trick/makefiles/config_user_cmake.mk.in + ${CMAKE_BINARY_DIR}/share/trick/makefiles/config_user.mk + @ONLY +) -if(USE_ER7_UTILS) - add_definitions( -DUSE_ER7_UTILS_INTEGRATORS) +# ────────────────────────────────────────────────────────────────────────── +# Phase 2 — core native build: ICG, io_src, archives, SWIG +# ────────────────────────────────────────────────────────────────────────── +find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Embed) + +# Flags shared by every Trick-core compile target, mirroring +# TRICK_SYSTEM_CXXFLAGS/TRICK_CXXFLAGS (Makefile.common:98-197). HDF5's +# -DHDF5/-I only apply to DataRecord/DRHDF5.cpp in the make build too (that +# file's own Makefile-local override — see sim_services/CMakeLists.txt), so +# it stays per-file here rather than global. GSL is different: Makefile.common +# itself puts -D_HAVE_GSL/-I on TRICK_SYSTEM_CXXFLAGS globally (every compiled +# file inherits it); MonteCarlo/Makefile's own local-looking GSL override is +# actually dead code (gated on a $(HAVE_GSL) variable nothing ever sets), so +# GSL flags belong here, build-wide, not scoped to one file. +add_library(trick_build_flags INTERFACE) +target_compile_features(trick_build_flags INTERFACE cxx_std_17) +# Position-independent code via the CMake property rather than a literal -fpic, +# so the compiler-appropriate flag is emitted. INTERFACE_POSITION_INDEPENDENT_CODE +# propagates POSITION_INDEPENDENT_CODE=ON to every target that links +# trick_build_flags (all the core archives + trick_pyip). Sims compiled by the +# make flow use -fpic; -fPIC is a compatible superset, and archive membership +# (the ar-t parity gate) is unaffected by the flag. +set_target_properties(trick_build_flags PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON) +target_compile_definitions(trick_build_flags INTERFACE + TRICK_VER=${TRICK_MAJOR} + TRICK_MINOR=${TRICK_MINOR} +) +target_include_directories(trick_build_flags INTERFACE + ${CMAKE_SOURCE_DIR}/trick_source + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/include/trick/compat +) +target_link_libraries(trick_build_flags INTERFACE Trick::udunits2) +if(TRICK_USE_ER7_UTILS) + target_compile_definitions(trick_build_flags INTERFACE USE_ER7_UTILS_INTEGRATORS) + if(EXISTS ${CMAKE_SOURCE_DIR}/trick_source/er7_utils/CheckpointHelper) + target_compile_definitions(trick_build_flags INTERFACE USE_ER7_UTILS_CHECKPOINTHELPER) + endif() endif() - -if(GSL_FOUND) - add_definitions( -D_HAVE_GSL) +if(TRICK_FORCE_32BIT) + target_compile_options(trick_build_flags INTERFACE -m32) + target_link_options(trick_build_flags INTERFACE -m32) endif() - -if(USE_MONGOOSE) - add_definitions(-DUSE_MONGOOSE) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options(trick_build_flags INTERFACE -fcolor-diagnostics) endif() - -include_directories( ${CMAKE_BINARY_DIR}/include) -include_directories( ${CMAKE_BINARY_DIR}/include/trick/compat) - -file(COPY bin DESTINATION ${CMAKE_BINARY_DIR}) -file(COPY include DESTINATION ${CMAKE_BINARY_DIR}) -file(COPY libexec DESTINATION ${CMAKE_BINARY_DIR}) -file(COPY share DESTINATION ${CMAKE_BINARY_DIR}) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/include/mongoose) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp_src/io_src) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp_src/lex_yacc) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp_src/mongoose) -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp_src/swig) -# copy er7_util header files to build directory -file(GLOB_RECURSE ER7_UTIL_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/trick_source/er7_utils ${CMAKE_CURRENT_SOURCE_DIR}/trick_source/er7_utils/*.hh) -foreach ( infile ${ER7_UTIL_HEADERS} ) - get_filename_component(dir ${infile} DIRECTORY) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/trick_source/er7_utils/${infile} DESTINATION "${CMAKE_BINARY_DIR}/include/er7_utils/${dir}") -endforeach(infile) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/share/trick/makefiles/config_user_cmake.mk.in ${CMAKE_BINARY_DIR}/share/trick/makefiles/config_user.mk) - -############################################################### -# mongoose lib -############################################################### -if(USE_MONGOOSE) -add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/include/mongoose/mongoose.h - COMMAND curl --retry 4 -O https://raw.githubusercontent.com/cesanta/mongoose/6.16/mongoose.h - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/include/mongoose -) - -add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/temp_src/mongoose/mongoose.c - COMMAND curl --retry 4 -O https://raw.githubusercontent.com/cesanta/mongoose/6.16/mongoose.c - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/temp_src/mongoose - DEPENDS ${CMAKE_BINARY_DIR}/include/mongoose/mongoose.h -) - -add_library(mongoose STATIC ${CMAKE_BINARY_DIR}/temp_src/mongoose/mongoose.c) -target_include_directories( mongoose PUBLIC ${CMAKE_BINARY_DIR}/include/mongoose ) +# USE_CIVETWEB/CIVETWEB_HOME (not the raw TRICK_CIVETWEB_HOME cache option) +# are what cmake/TrickPrograms.cmake actually resolved detection to — an +# unset TRICK_CIVETWEB_HOME can still auto-detect civetweb.h at /usr and set +# USE_CIVETWEB=1, matching config_user.mk, so this must gate on the same +# variables config_user.mk uses (see A1/tr_civetweb_home.m4). +if(USE_CIVETWEB) + target_compile_definitions(trick_build_flags INTERFACE USE_CIVETWEB) + target_include_directories(trick_build_flags INTERFACE ${CIVETWEB_HOME}/include) +endif() +if(GSL_HOME) + target_compile_definitions(trick_build_flags INTERFACE _HAVE_GSL) + # Makefile.common:164-177's nested ifneq excludes both /usr and + # /usr/local (the latter for e.g. Intel-mac Homebrew, whose default + # prefix is /usr/local rather than Apple Silicon's /opt/homebrew) from + # needing an explicit -I, since both are already on the compiler's + # default include search path. + if(NOT GSL_HOME STREQUAL "/usr" AND NOT GSL_HOME STREQUAL "/usr/local") + target_include_directories(trick_build_flags INTERFACE ${GSL_HOME}/include) + endif() endif() -############################################################### -# io_src files -############################################################### - -set( IO_SRC - ${CMAKE_BINARY_DIR}/temp_src/io_src/class_map.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ABM_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_AttributesMap.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_BC635Clock.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_CheckPointAgent.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_CheckPointRestart.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Clock.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_CommandLineArguments.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DRAscii.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DRBinary.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DRHDF5.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DataRecordDispatcher.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DataRecordGroup.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_DebugPause.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_EchoJobs.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_EnumAttributesMap.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Environment.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Euler_Cromer_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Euler_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Event.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_EventInstrument.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_EventManager.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_EventProcessor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Executive.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ExecutiveException.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ExternalApplication.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Flag.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_FrameDataRecordGroup.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_FrameLog.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_GetTimeOfDayClock.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_IPPython.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_IPPythonEvent.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ITimer.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_InputProcessor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_InstrumentBase.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_IntegLoopManager.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_IntegLoopScheduler.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_IntegLoopSimObject.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_JITEvent.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_JITInputFile.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_JSONVariableServer.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_JSONVariableServerThread.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_JobData.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MM4_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MSConnect.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MSSharedMem.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MSSocket.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MTV.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MalfunctionsTrickView.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Master.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MemoryManager.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageCout.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageFile.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageLCout.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessagePublisher.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageSubscriber.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageTCDevice.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MessageThreadedCout.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MonteCarlo.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MonteMonitor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MonteVar.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MultiDtIntegLoopScheduler.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_MultiDtIntegLoopSimObject.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_NL2_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_PlaybackFile.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RK2_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RK4_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RKF45_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RKF78_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RKG4_Integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RealtimeSync.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RemoteShell.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RtiEvent.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RtiExec.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RtiList.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_RtiStager.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_STLInterface.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ScheduledJobQueue.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Scheduler.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Sie.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_SimControlPanel.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_SimObject.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_SimTime.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Slave.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_StripChart.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_TPROCTEClock.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ThreadBase.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ThreadTrigger.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Threads.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Timer.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_TrickView.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_UCFn.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_UdUnits.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Unit.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_UnitTest.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_UnitsMap.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_VariableServer.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_VariableServerListenThread.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_VariableServerReference.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_VariableServerThread.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_Zeroconf.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_attributes.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_dllist.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_io_alloc.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_lqueue.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_lstack.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_message_type.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_mm_error.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ms_sim_mode.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_n_choose_m.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_parameter_types.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rand_generator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_reference.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_reference_frame.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_regula_falsi.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_sim_mode.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_tc.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_time_offset.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_trick_error_hndlr.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_tsm.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_units_conv.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_value.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_var.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_variable_server_sync_types.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_wave_form.cpp -) - -set( ER7_UTILS_IO_SRC - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_abm4_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_abm4_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_abm4_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_base_integration_group.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_beeman_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_beeman_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_bogus_integration_controls.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_deletable.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_euler_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_euler_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_euler_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_generalized_position_derivative.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrable_object.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integration_controls.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integration_messages.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integration_technique.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_constructor_factory.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_interface.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_result.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_result_merger.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_integrator_result_merger_container.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_left_quaternion_functions.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_mm4_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_mm4_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_nl2_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_nl2_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_position_verlet_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_position_verlet_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_priming_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_priming_integration_controls.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_priming_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_priming_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_ratio128.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_heun_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_heun_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_heun_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_midpoint_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_midpoint_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk2_midpoint_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk4_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk4_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk4_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rk4_second_order_ode_integrator_base.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf45_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf45_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf45_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf78_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf78_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkf78_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkg4_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkg4_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_rkg4_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_single_cycle_integration_controls.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_standard_integration_controls.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_state_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_symplectic_euler_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_symplectic_euler_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_time_interface.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_trick_first_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_trick_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_trick_second_order_ode_integrator.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_uint128.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_velocity_verlet_integrator_constructor.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_velocity_verlet_second_order_ode_integrator.cpp -) - -set(ENV{TRICK_ICG_EXCLUDE} ${CMAKE_BINARY_DIR}/include/mongoose) -set(ICG_FLAGS -I${CMAKE_BINARY_DIR}/include -I${CMAKE_BINARY_DIR}/include/trick/compat -I${UDUNITS2_INCLUDES} -DTRICK_VER=${TRICK_MAJOR} -DUSE_ER7_UTILS_INTEGRATORS) -add_custom_command(OUTPUT ${IO_SRC} ${ER7_UTILS_IO_SRC} - COMMAND TRICK_HOME=${CMAKE_BINARY_DIR} TRICK_ICG_EXCLUDE=${CMAKE_BINARY_DIR}/include/mongoose ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/trick-ICG -force -sim_services -m -n -o ${CMAKE_BINARY_DIR}/temp_src/io_src ${ICG_FLAGS} ${CMAKE_BINARY_DIR}/include/trick/files_to_ICG.hh - DEPENDS trick-ICG -) - -add_library( trick STATIC $ $ ${IO_SRC}) -target_include_directories( trick PUBLIC ${UDUNITS2_INCLUDES} ) - -add_library( er7_utils STATIC $ ${ER7_UTILS_IO_SRC}) - -# fake dependency to avoid double ICG -add_dependencies(er7_utils trick) - -############################################################### -# libtrick_pyip.a -############################################################### - -set( TRICK_SWIG_SRC - trick_source/trick_swig/PrimitiveAttributesMap - trick_source/trick_swig/swig_convert_units - trick_source/trick_swig/swig_global_vars -) - -# Generated SWIG files -set( SWIG_SRC - ${CMAKE_BINARY_DIR}/temp_src/swig/sim_services_wrap - ${CMAKE_BINARY_DIR}/temp_src/swig/swig_double_wrap - ${CMAKE_BINARY_DIR}/temp_src/swig/swig_int_wrap - ${CMAKE_BINARY_DIR}/temp_src/swig//swig_ref_wrap -) - -set( SWIG_SRC_BASENAME - sim_services - swig_double - swig_int - swig_ref -) +add_subdirectory(trick_source/codegen/Interface_Code_Gen) +include(TrickICG) -set(SWIG_FLAGS -DUSE_ER7_UTILS_INTEGRATORS) -if(GSL_FOUND) - list( APPEND SWIG_FLAGS -D_HAVE_GSL ) +add_subdirectory(trick_source/sim_services) +add_subdirectory(trick_source/trick_utils) +if(TRICK_USE_ER7_UTILS) + add_subdirectory(trick_source/er7_utils) endif() - -if(USE_MONGOOSE) - list( APPEND SWIG_FLAGS -DUSE_MONGOOSE) - list( APPEND IO_SRC - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_WebServer.cpp - ${CMAKE_BINARY_DIR}/temp_src/io_src/io_WebSocketSession.cpp - ) +add_subdirectory(trick_source/trick_swig) + +# libtrick.a = sim_services + trick_utils objects (minus MemoryManager and +# the trick_utils dirs with their own archives) + the non-er7_utils io_src +# objects (A3). +add_library(trick STATIC + $ + $ + ${TRICK_IO_SOURCES} +) +target_link_libraries(trick PUBLIC trick_build_flags) +add_dependencies(trick trick_io_src_gen) + +# ────────────────────────────────────────────────────────────────────────── +# Phase 4 — optional components: civetweb, Java GUIs, data_products +# ────────────────────────────────────────────────────────────────────────── +if(USE_CIVETWEB) + add_subdirectory(trick_source/web/CivetServer) endif() -foreach ( infile ${SWIG_SRC_BASENAME} ) - add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/temp_src/swig/${infile}_wrap.cpp - COMMAND ${SWIG_EXECUTABLE} ${SWIG_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/trick_source -I${CMAKE_CURRENT_SOURCE_DIR}/include -I${CMAKE_CURRENT_SOURCE_DIR} -c++ -python -includeall -ignoremissing -w201,362,389,451 -o $@ -outdir ${CMAKE_BINARY_DIR}/share/trick/swig ${CMAKE_CURRENT_SOURCE_DIR}/trick_source/trick_swig/${infile}.i - ) -endforeach(infile) - -add_library( trick_pyip STATIC $ ${TRICK_SWIG_SRC} ${SWIG_SRC}) -target_include_directories( trick_pyip PUBLIC ${PYTHON_INCLUDE_DIRS} ) -target_include_directories( trick_pyip PUBLIC ${UDUNITS2_INCLUDES} ) -if(GSL_FOUND) - target_include_directories( trick_pyip PUBLIC ${GSL_INCLUDE_DIRS} ) +if(TRICK_USE_JAVA) + add_subdirectory(trick_source/java) endif() -target_include_directories( trick_pyip PUBLIC trick_source ) - -############################################################### -# libtrickHTTP.a -############################################################### -if(USE_MONGOOSE) -set( TRICKHTTP_SRC - trick_source/web/HttpServer/src/VariableServerSession - trick_source/web/HttpServer/src/VariableServerVariable - trick_source/web/HttpServer/src/WebServer - trick_source/web/HttpServer/src/http_GET_handlers - trick_source/web/HttpServer/src/simpleJSON -) -add_library( trickHTTP STATIC ${TRICKHTTP_SRC}) -add_dependencies( trickHTTP mongoose) +if(TRICK_BUILD_DP) + add_subdirectory(trick_source/data_products) endif() -############################################################### -# Other Trick libraries -############################################################### -add_subdirectory(trick_source/codegen/Interface_Code_Gen) -add_subdirectory(trick_source/er7_utils) -add_subdirectory(trick_source/sim_services) -add_subdirectory(trick_source/trick_utils) -add_subdirectory(trick_source/java) -add_subdirectory(trick_source/data_products) +# ────────────────────────────────────────────────────────────────────────── +# Phase 3 — install rules, stage target, CTest +# ────────────────────────────────────────────────────────────────────────── +include(TrickInstall) +include(TrickTest) diff --git a/CMakeModules/FindLLVM.cmake b/CMakeModules/FindLLVM.cmake deleted file mode 100644 index 2424012fe..000000000 --- a/CMakeModules/FindLLVM.cmake +++ /dev/null @@ -1,201 +0,0 @@ -# - Find LLVM headers and libraries. -# This module locates LLVM and adapts the llvm-config output for use with -# CMake. -# -# A given list of COMPONENTS is passed to llvm-config. -# -# The following variables are defined: -# LLVM_FOUND - true if LLVM was found -# LLVM_CXXFLAGS - C++ compiler flags for files that include LLVM headers. -# LLVM_HOST_TARGET - Target triple used to configure LLVM. -# LLVM_INCLUDE_DIRS - Directory containing LLVM include files. -# LLVM_LDFLAGS - Linker flags to add when linking against LLVM -# (includes -LLLVM_LIBRARY_DIRS). -# LLVM_LIBRARIES - Full paths to the library files to link against. -# LLVM_LIBRARY_DIRS - Directory containing LLVM libraries. -# LLVM_NATIVE_ARCH - Backend corresponding to LLVM_HOST_TARGET, e.g., -# X86 for x86_64 and i686 hosts. -# LLVM_ROOT_DIR - The root directory of the LLVM installation. -# llvm-config is searched for in ${LLVM_ROOT_DIR}/bin. -# LLVM_VERSION_MAJOR - Major version of LLVM. -# LLVM_VERSION_MINOR - Minor version of LLVM. -# LLVM_VERSION_STRING - Full LLVM version string (e.g. 6.0.0svn). -# LLVM_VERSION_BASE_STRING - Base LLVM version string without git/svn suffix (e.g. 6.0.0). -# -# Note: The variable names were chosen in conformance with the offical CMake -# guidelines, see ${CMAKE_ROOT}/Modules/readme.txt. - -# Try suffixed versions to pick up the newest LLVM install available on Debian -# derivatives. -# We also want an user-specified LLVM_ROOT_DIR to take precedence over the -# system default locations such as /usr/local/bin. Executing find_program() -# multiples times is the approach recommended in the docs. -set(llvm_config_names llvm-config-9.0 llvm-config90 - llvm-config-8.0 llvm-config80 - llvm-config-7.0 llvm-config70 - llvm-config-6.0 llvm-config60 - llvm-config-5.0 llvm-config50 - llvm-config-4.0 llvm-config40 - llvm-config-3.9 llvm-config39 - llvm-config) -find_program(LLVM_CONFIG - NAMES ${llvm_config_names} - PATHS ${LLVM_ROOT_DIR}/bin /usr/local/opt/llvm/bin NO_DEFAULT_PATH - DOC "Path to llvm-config tool.") -find_program(LLVM_CONFIG NAMES ${llvm_config_names}) - -# Prints a warning/failure message depending on the required/quiet flags. Copied -# from FindPackageHandleStandardArgs.cmake because it doesn't seem to be exposed. -macro(_LLVM_FAIL _msg) - if(LLVM_FIND_REQUIRED) - message(FATAL_ERROR "${_msg}") - else() - if(NOT LLVM_FIND_QUIETLY) - message(STATUS "${_msg}") - endif() - endif() -endmacro() - - -if(NOT LLVM_CONFIG) - if(NOT LLVM_FIND_QUIETLY) - message(WARNING "Could not find llvm-config (LLVM >= ${LLVM_FIND_VERSION}). Try manually setting LLVM_CONFIG to the llvm-config executable of the installation to use.") - endif() -else() - macro(llvm_set var flag) - if(LLVM_FIND_QUIETLY) - set(_quiet_arg ERROR_QUIET) - endif() - set(result_code) - execute_process( - COMMAND ${LLVM_CONFIG} --${flag} - RESULT_VARIABLE result_code - OUTPUT_VARIABLE LLVM_${var} - OUTPUT_STRIP_TRAILING_WHITESPACE - ${_quiet_arg} - ) - if(result_code) - _LLVM_FAIL("Failed to execute llvm-config ('${LLVM_CONFIG}', result code: '${result_code})'") - else() - if(${ARGV2}) - file(TO_CMAKE_PATH "${LLVM_${var}}" LLVM_${var}) - endif() - endif() - endmacro() - macro(llvm_set_libs var flag components) - if(LLVM_FIND_QUIETLY) - set(_quiet_arg ERROR_QUIET) - endif() - set(result_code) - execute_process( - COMMAND ${LLVM_CONFIG} --${flag} ${components} - RESULT_VARIABLE result_code - OUTPUT_VARIABLE tmplibs - OUTPUT_STRIP_TRAILING_WHITESPACE - ${_quiet_arg} - ) - if(result_code) - _LLVM_FAIL("Failed to execute llvm-config ('${LLVM_CONFIG}', result code: '${result_code})'") - else() - file(TO_CMAKE_PATH "${tmplibs}" tmplibs) - string(REGEX MATCHALL "${pattern}[^ ]+" LLVM_${var} ${tmplibs}) - endif() - endmacro() - - llvm_set(VERSION_STRING version) - llvm_set(CXXFLAGS cxxflags) - llvm_set(HOST_TARGET host-target) - llvm_set(INCLUDE_DIRS includedir true) - llvm_set(ROOT_DIR prefix true) - - # The LLVM version string _may_ contain a git/svn suffix, so match only the x.y.z part - string(REGEX MATCH "^[0-9]+[.][0-9]+[.][0-9]+" LLVM_VERSION_BASE_STRING "${LLVM_VERSION_STRING}") - - if(NOT ${LLVM_VERSION_STRING} MATCHES "^3\\.4\\..*") - llvm_set(ENABLE_ASSERTIONS assertion-mode) - endif() - - # Versions below 4.0 do not support components debuginfomsf and demangle - if(${LLVM_VERSION_STRING} MATCHES "^3\\..*") - list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfomsf" index) - list(REMOVE_ITEM LLVM_FIND_COMPONENTS "demangle" index) - endif() - # Versions below 6.0 do not support component windowsmanifest - if(${LLVM_VERSION_STRING} MATCHES "^[3-5]\\..*") - list(REMOVE_ITEM LLVM_FIND_COMPONENTS "windowsmanifest" index) - endif() - - llvm_set(LDFLAGS ldflags) - # In LLVM 3.5+, the system library dependencies (e.g. "-lz") are accessed - # using the separate "--system-libs" flag. - if(NOT ${LLVM_VERSION_STRING} MATCHES "^3\\.4\\..*") - llvm_set(SYSTEM_LIBS system-libs) - endif() - string(REPLACE "\n" " " LLVM_LDFLAGS "${LLVM_LDFLAGS} ${LLVM_SYSTEM_LIBS}") - string(STRIP ${LLVM_LDFLAGS} LLVM_LDFLAGS) - llvm_set(LIBRARY_DIRS libdir true) - llvm_set_libs(LIBRARIES libs "${LLVM_FIND_COMPONENTS}") - # LLVM bug: llvm-config --libs tablegen returns -lLLVM-3.8.0 - # but code for it is not in shared library - if("${LLVM_FIND_COMPONENTS}" MATCHES "tablegen") - if (NOT "${LLVM_LIBRARIES}" MATCHES "LLVMTableGen") - set(LLVM_LIBRARIES "${LLVM_LIBRARIES};-lLLVMTableGen") - endif() - endif() - - # Versions below 4.0 do not support llvm-config --cmakedir - if(${LLVM_VERSION_STRING} MATCHES "^3\\..*") - set(LLVM_CMAKEDIR ${LLVM_LIBRARY_DIRS}/cmake/llvm) - else() - llvm_set(CMAKEDIR cmakedir) - endif() - - llvm_set(TARGETS_TO_BUILD targets-built) - string(REGEX MATCHALL "${pattern}[^ ]+" LLVM_TARGETS_TO_BUILD ${LLVM_TARGETS_TO_BUILD}) - - # Parse LLVM_NATIVE_ARCH manually from LLVMConfig.cmake; including it leads to issues like - # https://github.com/ldc-developers/ldc/issues/3079. - if(EXISTS "${LLVM_CMAKEDIR}/LLVMConfig.cmake") - file(STRINGS "${LLVM_CMAKEDIR}/LLVMConfig.cmake" LLVM_NATIVE_ARCH LIMIT_COUNT 1 REGEX "^set\\(LLVM_NATIVE_ARCH (.+)\\)$") - string(REGEX MATCH "set\\(LLVM_NATIVE_ARCH (.+)\\)" LLVM_NATIVE_ARCH "${LLVM_NATIVE_ARCH}") - set(LLVM_NATIVE_ARCH ${CMAKE_MATCH_1}) - message(STATUS "LLVM_NATIVE_ARCH: ${LLVM_NATIVE_ARCH}") - endif() -endif() - -# On CMake builds of LLVM, the output of llvm-config --cxxflags does not -# include -fno-rtti, leading to linker errors. Be sure to add it. -if(NOT MSVC AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))) - if(NOT ${LLVM_CXXFLAGS} MATCHES "-fno-rtti") - set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS} -fno-rtti") - endif() -endif() - -# Remove some clang-specific flags for gcc. -if(CMAKE_COMPILER_IS_GNUCXX) - string(REPLACE "-Wcovered-switch-default " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) - string(REPLACE "-Wstring-conversion " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) - string(REPLACE "-fcolor-diagnostics " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) - # this requires more recent gcc versions (not supported by 4.9) - string(REPLACE "-Werror=unguarded-availability-new " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) -endif() - -# Remove gcc-specific flags for clang. -if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - string(REPLACE "-Wno-maybe-uninitialized " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) -endif() - -string(REGEX REPLACE "([0-9]+).*" "\\1" LLVM_VERSION_MAJOR "${LLVM_VERSION_STRING}" ) -string(REGEX REPLACE "[0-9]+\\.([0-9]+).*[A-Za-z]*" "\\1" LLVM_VERSION_MINOR "${LLVM_VERSION_STRING}" ) -string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*[A-Za-z]*" "\\1" LLVM_VERSION_PATCH "${LLVM_VERSION_STRING}" ) - -if (${LLVM_VERSION_STRING} VERSION_LESS ${LLVM_FIND_VERSION}) - message(FATAL_ERROR "Unsupported LLVM version found ${LLVM_VERSION_STRING}. At least version ${LLVM_FIND_VERSION} is required.") -endif() - -# Use the default CMake facilities for handling QUIET/REQUIRED. -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(LLVM - REQUIRED_VARS LLVM_ROOT_DIR LLVM_HOST_TARGET - VERSION_VAR LLVM_VERSION_STRING) diff --git a/CMakeModules/FindMaven.cmake b/CMakeModules/FindMaven.cmake deleted file mode 100644 index 890982426..000000000 --- a/CMakeModules/FindMaven.cmake +++ /dev/null @@ -1,19 +0,0 @@ - -# FindMaven -# -------- -# -# Find mvn -# -# This module looks for mvn. This module defines the following values: -# -# :: -# -# MAVEN_EXECUTABLE: the full path to the mvn tool. -# MAVEN_FOUND: True if mvn has been found. - -find_program(MAVEN_EXECUTABLE mvn) -include (FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Maven FOUND_VAR MAVEN_FOUND REQUIRED_VARS MAVEN_EXECUTABLE) -if(MAVEN_FIND_REQUIRED AND NOT MAVEN_FOUND) - message(FATAL_ERROR "Could not find mvn") -endif() diff --git a/CMakeModules/FindTee.cmake b/CMakeModules/FindTee.cmake deleted file mode 100644 index 59dddb830..000000000 --- a/CMakeModules/FindTee.cmake +++ /dev/null @@ -1,21 +0,0 @@ - -# FindTee -# -------- -# -# Find tee -# -# This module looks for tee. This module defines the following values: -# -# :: -# -# TEE_EXECUTABLE: the full path to the tee tool. -# TEE_FOUND: True if tee has been found. - -find_program(TEE_EXECUTABLE tee) -mark_as_advanced( TEE_EXECUTABLE ) - -include (FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Tee FOUND_VAR REQUIRED_VARS TEE_EXECUTABLE) -if(Tee_FIND_REQUIRED AND NOT TEE_FOUND) - message(FATAL_ERROR "Could not find tee") -endif() diff --git a/CMakeModules/FindUDUNITS2.cmake b/CMakeModules/FindUDUNITS2.cmake deleted file mode 100644 index d1445a0e1..000000000 --- a/CMakeModules/FindUDUNITS2.cmake +++ /dev/null @@ -1,92 +0,0 @@ -# - Find UDUNITS2 -# Find the native UDUNITS2 includes and library -# -# UDUNITS2_INCLUDES - where to find udunits2.h -# UDUNITS2_LIBRARIES - libraries to link with -# UDUNITS2_FOUND - True if UDUNITS2 was found. - -message(STATUS "UDUNITS2_ROOT = ${UDUNITS2_ROOT}") -if (UDUNITS2_INCLUDES) - # Already in cache, be silent - set (UDUNITS2_FIND_QUIETLY TRUE) -endif (UDUNITS2_INCLUDES) - -find_path (UDUNITS2_INCLUDES udunits2.h - HINTS "${UDUNITS2_ROOT}/include" "$ENV{UDUNITS2_ROOT}/include" - PATH_SUFFIXES "udunits2" - DOC "Path to udunits2.h") - -# UDUNITS2 headers might be in .../include or .../include/udunits2. -# We try both. -if (${UDUNITS2_INCLUDES} MATCHES "udunits2/?$") - string(REGEX REPLACE "/include/udunits2/?$" "/lib" - UDUNITS2_LIB_HINT ${UDUNITS2_INCLUDES}) -else() - string(REGEX REPLACE "/include/?$" "/lib" - UDUNITS2_LIB_HINT ${UDUNITS2_INCLUDES}) -endif() - -find_library (UDUNITS2_LIBRARIES - NAMES udunits2 - HINTS ${UDUNITS2_LIB_HINT}) - -set(UDUNITS2_TEST_SRC " -#include - -int main(int argc, char **argv) { - ut_system *s = ut_read_xml(NULL); - ut_free_system(s); - return 0; -} -") - -if ((NOT UDUNITS2_LIBRARIES) OR (NOT UDUNITS2_INCLUDES)) - message(STATUS "Trying to find UDUNITS-2 using LD_LIBRARY_PATH (we're desperate)...") - - file(TO_CMAKE_PATH "$ENV{LD_LIBRARY_PATH}" LD_LIBRARY_PATH) - - find_library(UDUNITS2_LIBRARIES - NAMES udunits2 - HINTS ${LD_LIBRARY_PATH}) - - if (UDUNITS2_LIBRARIES) - get_filename_component(UDUNITS2_LIB_DIR ${UDUNITS2_LIBRARIES} PATH) - string(REGEX REPLACE "/lib/?$" "/include" - UDUNITS2_H_HINT ${UDUNITS2_LIB_DIR}) - - find_path (UDUNITS2_INCLUDES udunits2.h - HINTS ${UDUNITS2_H_HINT} - PATH_SUFFIXES "udunits2" - DOC "Path to udunits2.h") - endif() -endif() - -include (CheckCSourceRuns) - -set(CMAKE_REQUIRED_INCLUDES ${UDUNITS2_INCLUDES}) -set(CMAKE_REQUIRED_LIBRARIES ${UDUNITS2_LIBRARIES}) -check_c_source_runs("${UDUNITS2_TEST_SRC}" UDUNITS2_WORKS_WITHOUT_EXPAT) - -if(${UDUNITS2_WORKS_WITHOUT_EXPAT}) - #message(STATUS "UDUNITS-2 does not require expat") -else() - find_package(EXPAT REQUIRED) - - set(CMAKE_REQUIRED_INCLUDES ${UDUNITS2_INCLUDES} ${EXPAT_INCLUDE_DIRS}) - set(CMAKE_REQUIRED_LIBRARIES ${UDUNITS2_LIBRARIES} ${EXPAT_LIBRARIES}) - check_c_source_runs("${UDUNITS2_TEST_SRC}" UDUNITS2_WORKS_WITH_EXPAT) - - if(NOT ${UDUNITS2_WORKS_WITH_EXPAT}) - message(FATAL_ERROR "UDUNITS-2 does not seem to work with or without expat") - endif() - - #message(STATUS "UDUNITS-2 requires EXPAT") - set (UDUNITS2_LIBRARIES "${UDUNITS2_LIBRARIES};${EXPAT_LIBRARIES}" CACHE STRING "" FORCE) -endif() - -# handle the QUIETLY and REQUIRED arguments and set UDUNITS2_FOUND to TRUE if -# all listed variables are TRUE -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args (UDUNITS2 DEFAULT_MSG UDUNITS2_LIBRARIES UDUNITS2_INCLUDES) - -mark_as_advanced (UDUNITS2_LIBRARIES UDUNITS2_INCLUDES) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..d3faf57cc --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,30 @@ +{ + "version": 3, + "cmakeMinimumRequired": { "major": 3, "minor": 20, "patch": 0 }, + "configurePresets": [ + { + "name": "default", + "displayName": "Default", + "description": "Auto-detect all dependencies from the environment", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "macos-homebrew", + "displayName": "macOS (Homebrew)", + "description": "Point detection at Homebrew's LLVM, since Apple's system clang lacks the libraries ICG needs", + "inherits": "default", + "cacheVariables": { + "LLVM_HOME": "/opt/homebrew/opt/llvm" + } + }, + { + "name": "rhel", + "displayName": "RHEL-family (RHEL/Rocky/Oracle Linux)", + "description": "Same detection as default; installs to lib64 automatically per config_Linux.mk's /etc/redhat-release check", + "inherits": "default" + } + ] +} diff --git a/CMakeTestFiles/TestICGLinkedLibs.cpp b/CMakeTestFiles/TestICGLinkedLibs.cpp deleted file mode 100644 index 33ce68915..000000000 --- a/CMakeTestFiles/TestICGLinkedLibs.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// `llvm/Support/Host.h` is deprecated in favour of `llvm/TargetParser/Host.h` since clang 17 -#if LIBCLANG_MAJOR > 16 -#include "llvm/TargetParser/Host.h" -#else -#include "llvm/Support/Host.h" -#endif -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" - -#include "clang/Basic/Builtins.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/FileManager.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Parse/ParseAST.h" - -int main() { - return 0; -} \ No newline at end of file diff --git a/cmake/FindLLVMClang.cmake b/cmake/FindLLVMClang.cmake new file mode 100644 index 000000000..77af818ac --- /dev/null +++ b/cmake/FindLLVMClang.cmake @@ -0,0 +1,101 @@ +# Locate llvm-config and derive the LLVM/clang paths Trick's ICG needs. +# Mirrors autoconf/m4/tr_llvm_home.m4 and configure.ac:198-220. +# +# Honors the LLVM_HOME cache variable (equivalent to --with-llvm=DIR); when +# unset, searches the same fallback directories tr_llvm_home.m4 does, plus +# the Intel-mac homebrew prefix for parity with the old FindLLVM.cmake. +# +# Exports: +# LLVM_CONFIG_EXECUTABLE, LLVM_HOME (prefix), LLVM_LIB_DIR, LLVM_BIN_DIR, +# LLVM_INCLUDE_DIR, LLVM_VERSION_STRING, CLANG_EXECUTABLE, CLANG_VERSION + +if(LLVM_HOME) + find_program(LLVM_CONFIG_EXECUTABLE + NAMES llvm-config + PATHS "${LLVM_HOME}/bin" + NO_DEFAULT_PATH + ) + if(NOT LLVM_CONFIG_EXECUTABLE) + message(FATAL_ERROR "could not find llvm-config") + endif() +else() + find_program(LLVM_CONFIG_EXECUTABLE + NAMES llvm-config + PATHS + /usr/lib64/llvm20/bin + /usr/lib64/llvm/bin + /bin + /usr/bin + /usr/local/bin + /sw/bin + /opt/homebrew/opt/llvm/bin + /usr/local/opt/llvm/bin + NO_DEFAULT_PATH + ) + if(NOT LLVM_CONFIG_EXECUTABLE) + find_program(LLVM_CONFIG_EXECUTABLE NAMES llvm-config) + endif() + if(NOT LLVM_CONFIG_EXECUTABLE) + message(FATAL_ERROR "could not find llvm-config") + endif() + execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --prefix + OUTPUT_VARIABLE LLVM_HOME + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --libdir + OUTPUT_VARIABLE LLVM_LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --bindir + OUTPUT_VARIABLE LLVM_BIN_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +execute_process( + COMMAND ${LLVM_CONFIG_EXECUTABLE} --version + OUTPUT_VARIABLE LLVM_VERSION_STRING + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +if(NOT EXISTS "${LLVM_INCLUDE_DIR}/clang/Basic/LLVM.h") + message(FATAL_ERROR "could not find clang development headers") +endif() +if(NOT EXISTS "${LLVM_LIB_DIR}/libLLVMSupport.a") + message(FATAL_ERROR "could not find clang library files in ${LLVM_LIB_DIR}") +endif() + +find_program(CLANG_EXECUTABLE + NAMES clang + PATHS "${LLVM_BIN_DIR}" /bin /usr/bin /usr/local/bin /sw/bin + NO_DEFAULT_PATH +) +if(NOT CLANG_EXECUTABLE) + message(FATAL_ERROR "could not find clang") +endif() + +if(LLVM_VERSION_STRING VERSION_LESS "3.4.2") + message(FATAL_ERROR "Trick requires llvm/clang version >= 3.4.2, found ${LLVM_VERSION_STRING}") +endif() + +# autoconf/m4/tr_clang_version.m4 derives CLANG_VERSION from `clang --version` +# rather than trusting llvm-config, since some distros patch clang's reported +# version away from LLVM's. Replicate that here for parity. +execute_process( + COMMAND ${CLANG_EXECUTABLE} --version + OUTPUT_VARIABLE _tr_clang_version_output + OUTPUT_STRIP_TRAILING_WHITESPACE +) +string(REGEX MATCH "version ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${_tr_clang_version_output}") +set(CLANG_VERSION "${CMAKE_MATCH_1}") +if(CLANG_VERSION AND CLANG_VERSION VERSION_LESS "3.4.2") + message(FATAL_ERROR "Trick requires llvm/clang version >= 3.4.2, found ${CLANG_VERSION}") +endif() diff --git a/cmake/FindUDUNITS2.cmake b/cmake/FindUDUNITS2.cmake new file mode 100644 index 000000000..b313ec8b1 --- /dev/null +++ b/cmake/FindUDUNITS2.cmake @@ -0,0 +1,63 @@ +# UDUNITS2 detection, mirroring autoconf/m4/tr_udunits_home.m4 and +# configure.ac:260-302 exactly, including the exact rendered +# UDUNITS_INCLUDES / UDUNITS_LDFLAGS / UDUNITS_EXCLUDE strings +# config_user.mk consumes (TRICK_EXCLUDE += :@UDUNITS_EXCLUDE@ requires the +# variable to render empty rather than unset). +# +# Honors the UDUNITS_HOME cache variable (equivalent to --with-udunits=DIR). +# +# Exports: UDUNITS_INCLUDES, UDUNITS_LDFLAGS, UDUNITS_EXCLUDE +# Also defines an imported target Trick::udunits2 for later phases. + +set(UDUNITS_EXCLUDE "") + +if(NOT UDUNITS_HOME) + if(EXISTS "/usr/include/udunits2.h") + set(UDUNITS_INCLUDES "") + set(UDUNITS_LDFLAGS "-ludunits2") + set(_tr_udunits_header "/usr/include/udunits2.h") + elseif(EXISTS "/usr/include/udunits2/udunits2.h") + set(UDUNITS_INCLUDES "-I/usr/include/udunits2") + set(UDUNITS_LDFLAGS "-ludunits2") + set(_tr_udunits_header "/usr/include/udunits2/udunits2.h") + elseif(EXISTS "/opt/homebrew/include/udunits2.h") + set(UDUNITS_HOME "/opt/homebrew") + set(UDUNITS_INCLUDES "-I${UDUNITS_HOME}/include") + set(UDUNITS_LDFLAGS "-L${UDUNITS_HOME}/lib -ludunits2") + set(UDUNITS_EXCLUDE "${UDUNITS_HOME}") + set(_tr_udunits_header "${UDUNITS_HOME}/include/udunits2.h") + else() + message(FATAL_ERROR "could not find udunits2.h") + endif() +else() + set(UDUNITS_EXCLUDE "${UDUNITS_HOME}") + if(EXISTS "${UDUNITS_HOME}/include/udunits2.h") + set(UDUNITS_INCLUDES "-I${UDUNITS_HOME}/include") + set(UDUNITS_LDFLAGS "-Wl,-rpath,${UDUNITS_HOME}/lib -L${UDUNITS_HOME}/lib -ludunits2") + set(_tr_udunits_header "${UDUNITS_HOME}/include/udunits2.h") + elseif(EXISTS "${UDUNITS_HOME}/lib/udunits2.h") + set(UDUNITS_INCLUDES "-I${UDUNITS_HOME}/lib") + set(UDUNITS_LDFLAGS "-Wl,-rpath,${UDUNITS_HOME}/lib -L${UDUNITS_HOME}/lib -ludunits2") + set(_tr_udunits_header "${UDUNITS_HOME}/lib/udunits2.h") + else() + message(FATAL_ERROR "could not find udunits2") + endif() +endif() + +# AC_CHECK_LIB(udunits2, main, ...) — verify the library actually links. +find_library(UDUNITS2_LIBRARY + NAMES udunits2 + HINTS "${UDUNITS_HOME}/lib" +) +if(NOT UDUNITS2_LIBRARY) + message(FATAL_ERROR "could not find libudunits") +endif() + +if(NOT TARGET Trick::udunits2) + add_library(Trick::udunits2 UNKNOWN IMPORTED) + get_filename_component(_tr_udunits_incdir "${_tr_udunits_header}" DIRECTORY) + set_target_properties(Trick::udunits2 PROPERTIES + IMPORTED_LOCATION "${UDUNITS2_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${_tr_udunits_incdir}" + ) +endif() diff --git a/cmake/TestICGLinkedLibs.cpp b/cmake/TestICGLinkedLibs.cpp new file mode 100644 index 000000000..0d67b1f0d --- /dev/null +++ b/cmake/TestICGLinkedLibs.cpp @@ -0,0 +1,40 @@ +#include "clang/Basic/Builtins.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Parse/ParseAST.h" +#include "llvm/Support/CommandLine.h" +// `llvm/Support/Host.h` is deprecated in favour of `llvm/TargetParser/Host.h` since clang 17 +#if LIBCLANG_MAJOR > 16 +#include "llvm/TargetParser/Host.h" +#else +#include "llvm/Support/Host.h" +#endif +#include "llvm/Support/raw_ostream.h" + +#include + +// This TU is link-tested (not run) by cmake/TrickClangLibs.cmake to verify the +// selected C++ compiler can actually link the LLVM/Clang archives trick-ICG +// needs. main() must therefore *reference a std::string-returning LLVM symbol*, +// not just return: an empty main() links even when the compiler's C++ standard +// library (libc++ vs libstdc++) disagrees with the one LLVM was built against, +// because it pulls no library symbols — which lets a mismatched compiler slip +// past configure and only fail when trick-ICG itself is linked. +// +// llvm::sys::getDefaultTargetTriple() returns std::string and exists in every +// supported LLVM version, so the compiler emits a reference to *its* standard +// library's mangling of it (e.g. the libstdc++ [abi:cxx11] symbol under gcc vs +// the libc++ std::__1 symbol under a libc++ clang). That reference only +// resolves when the archives were built with the same standard library, so a +// mismatch turns into a link failure here — on any platform, without hardcoding +// per-OS/per-compiler assumptions. +int main() +{ + std::string triple = llvm::sys::getDefaultTargetTriple(); + return triple.empty() ? 1 : 0; +} diff --git a/cmake/TrickClangLibs.cmake b/cmake/TrickClangLibs.cmake new file mode 100644 index 000000000..92a433cae --- /dev/null +++ b/cmake/TrickClangLibs.cmake @@ -0,0 +1,127 @@ +# Implements the ICG_CLANGLIBS selection algorithm from +# autoconf/configure.ac:222-256 exactly, then sanity-checks the result with a +# try_compile against TestICGLinkedLibs.cpp. +# +# Requires LLVM_LIB_DIR and CLANG_VERSION (from FindLLVMClang.cmake). +# Exports: ICG_CLANGLIBS, TR_LLVM_LIBS, TR_LLVM_SYSTEM_LIBS, TR_LLVM_LDFLAGS +# (llvm-config --libs/--system-libs/--ldflags, the latter pre-filtered per +# platform — see below). trick_source/codegen/Interface_Code_Gen/CMakeLists.txt +# links trick-ICG from these instead of re-running llvm-config itself. + +if(NOT DEFINED LLVM_LIB_DIR) + message(FATAL_ERROR "TrickClangLibs.cmake requires LLVM_LIB_DIR (include FindLLVMClang first)") +endif() + +if(CLANG_VERSION AND CLANG_VERSION VERSION_GREATER_EQUAL "18.0.0") + set(_tr_old_clang_libs + "-lclangFrontend -lclangDriver -lclangSerialization -lclangParse -lclangSema -lclangAnalysis -lclangEdit -lclangAST -lclangASTMatchers -lclangAPINotes -lclangLex -lclangBasic" + ) +else() + set(_tr_old_clang_libs + "-lclangFrontend -lclangDriver -lclangSerialization -lclangParse -lclangSema -lclangAnalysis -lclangEdit -lclangAST -lclangLex -lclangBasic" + ) +endif() +set(_tr_new_clang_libs "-lclang-cpp") + +if(EXISTS "${LLVM_LIB_DIR}/libclangFrontend.a" OR EXISTS "${LLVM_LIB_DIR}/libclangFrontend.so") + set(ICG_CLANGLIBS "${_tr_old_clang_libs}") +elseif(EXISTS "${LLVM_LIB_DIR}/libclang-cpp.a" OR EXISTS "${LLVM_LIB_DIR}/libclang-cpp.so") + set(ICG_CLANGLIBS "${_tr_new_clang_libs}") +else() + message(FATAL_ERROR "could not find clang libs in LLVM library: \"${LLVM_LIB_DIR}\"") +endif() + +if(EXISTS "${LLVM_LIB_DIR}/libclangSupport.a") + set(ICG_CLANGLIBS "${ICG_CLANGLIBS} -lclangSupport") +endif() +if(EXISTS "${LLVM_LIB_DIR}/libclangOptions.a") + set(ICG_CLANGLIBS "${ICG_CLANGLIBS} -lclangOptions") +endif() +if(EXISTS "${LLVM_LIB_DIR}/libclangAnalysisLifetimeSafety.a") + set(ICG_CLANGLIBS "${ICG_CLANGLIBS} -lclangAnalysisLifetimeSafety") +endif() + +# Sanity-*link* a real clang/LLVM TU against the derived ICG_CLANGLIBS. This +# is the whole point of TestICGLinkedLibs.cpp: catch a wrong library +# selection at configure time rather than at Phase 2's trick-ICG link step. +# The link recipe mirrors trick_source/codegen/Interface_Code_Gen/Makefile +# exactly (CLANGLIBS/LLVMLDFLAGS/CXXFLAGS construction). +string(REGEX MATCH "^[0-9]+" _tr_llvm_version_major "${LLVM_VERSION_STRING}") + +execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --libs + OUTPUT_VARIABLE TR_LLVM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --system-libs + OUTPUT_VARIABLE _tr_llvm_system_libs_raw OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXECUTABLE} --ldflags + OUTPUT_VARIABLE TR_LLVM_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + +# TR_LLVM_SYSTEM_LIBS: --system-libs filtered per platform, computed once +# here and reused by both this file's sanity try_compile below and +# Interface_Code_Gen/CMakeLists.txt's trick-ICG link. +set(TR_LLVM_SYSTEM_LIBS "") +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(LLVM_VERSION_STRING VERSION_GREATER_EQUAL "3.5") + # Fedora adds -ledit as a system lib, but it isn't installed or required. + string(REPLACE "-ledit" "" TR_LLVM_SYSTEM_LIBS "${_tr_llvm_system_libs_raw}") + endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(TR_LLVM_SYSTEM_LIBS "${_tr_llvm_system_libs_raw}") +endif() + +set(_tr_icg_link_libs "${ICG_CLANGLIBS} ${TR_LLVM_LIBS} ${TR_LLVM_SYSTEM_LIBS}") +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + if(_tr_llvm_version_major GREATER_EQUAL 16) + set(_tr_icg_link_libs "${_tr_icg_link_libs} -lc++abi -lclang-cpp") + else() + set(_tr_icg_link_libs "${_tr_icg_link_libs} -lc++abi") + endif() +endif() + +if(_tr_llvm_version_major GREATER_EQUAL 16) + set(_tr_icg_cxx_std 17) +elseif(_tr_llvm_version_major GREATER_EQUAL 10) + set(_tr_icg_cxx_std 14) +else() + set(_tr_icg_cxx_std 11) +endif() + +separate_arguments(_tr_icg_link_libs_list NATIVE_COMMAND "-L${LLVM_LIB_DIR} ${TR_LLVM_LDFLAGS} ${_tr_icg_link_libs}") + +try_compile(TR_ICG_CLANG_HEADERS_COMPILE + ${CMAKE_BINARY_DIR}/CMakeFiles/TrickClangLibsCheck + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestICGLinkedLibs.cpp + CMAKE_FLAGS + "-DINCLUDE_DIRECTORIES=${LLVM_INCLUDE_DIR}" + COMPILE_DEFINITIONS + -DLIBCLANG_MAJOR=${_tr_llvm_version_major} + LINK_LIBRARIES + ${_tr_icg_link_libs_list} + CXX_STANDARD ${_tr_icg_cxx_std} + OUTPUT_VARIABLE TR_ICG_CLANG_HEADERS_COMPILE_OUTPUT +) +if(NOT TR_ICG_CLANG_HEADERS_COMPILE) + message(FATAL_ERROR +"trick-ICG cannot be linked against the LLVM/Clang libraries in + ${LLVM_LIB_DIR} +using + ${CMAKE_CXX_COMPILER} (${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}). + +The usual cause is a C++ standard-library (ABI) mismatch: the LLVM/Clang +archives are built against one standard library (libc++ or libstdc++) and the +selected C++ compiler defaults to the other, so the std::string / std::* symbols +the archives reference cannot be resolved. The compiler and LLVM must agree on +the standard library. + * macOS: Homebrew/system LLVM is built against libc++. Build with a libc++ + Clang -- the default 'c++'/Apple Clang, or Homebrew clang. GNU gcc/g++ uses + libstdc++ and has no working libc++ mode, so it cannot link these archives; + unset CC/CXX or set them to clang/clang++. + * Linux: distro LLVM is built against libstdc++; gcc and the system clang both + default to libstdc++, so either works. Avoid clang -stdlib=libc++ unless your + LLVM was also built that way. +Alternatively, point -DLLVM_HOME at an LLVM built with the same standard library +as your compiler. + +ICG_CLANGLIBS was: \"${ICG_CLANGLIBS}\" +Sanity-link output: +${TR_ICG_CLANG_HEADERS_COMPILE_OUTPUT}") +endif() diff --git a/cmake/TrickGTest.cmake b/cmake/TrickGTest.cmake new file mode 100644 index 000000000..2354eae25 --- /dev/null +++ b/cmake/TrickGTest.cmake @@ -0,0 +1,38 @@ +# GTEST_HOME detection + GTEST_CXXSTD derivation, mirroring +# autoconf/m4/tr_gtest.m4. +# +# Honors the GTEST_HOME cache variable; when unset, auto-detects like +# configure's "--with-gtest not given" branch. +# +# Exports: GTEST_HOME, GTEST_CXXSTD + +if(GTEST_HOME) + if(NOT EXISTS "${GTEST_HOME}/include/gtest") + message(FATAL_ERROR "could not find ${GTEST_HOME}/include/gtest") + endif() +elseif(EXISTS "/usr/include/gtest/gtest.h") + set(GTEST_HOME "/usr") +elseif(EXISTS "/opt/homebrew/include/gtest/gtest.h") + set(GTEST_HOME "/opt/homebrew") +else() + set(GTEST_HOME "") +endif() + +set(GTEST_CXXSTD "") +if(GTEST_HOME) + find_package(PkgConfig QUIET) + if(PKG_CONFIG_FOUND) + pkg_check_modules(TR_GTEST_PC QUIET gtest) + if(TR_GTEST_PC_VERSION) + if(TR_GTEST_PC_VERSION VERSION_GREATER_EQUAL "1.17") + set(GTEST_CXXSTD "-std=c++17") + else() + set(GTEST_CXXSTD "-std=c++14") + endif() + else() + message(WARNING "Could not determine gtest version via pkg-config") + endif() + else() + message(WARNING "pkg-config gtest not found, version detection skipped") + endif() +endif() diff --git a/cmake/TrickICG.cmake b/cmake/TrickICG.cmake new file mode 100644 index 000000000..226e6644d --- /dev/null +++ b/cmake/TrickICG.cmake @@ -0,0 +1,129 @@ +# io_src generation for Trick's own core build (Part C, Phase 2, step 3). +# +# Requires trick-ICG (add_subdirectory(trick_source/codegen/Interface_Code_Gen) +# already processed) plus the detection variables from Phase 1. +# +# ICG's output-file placement is dynamic — it discovers headers transitively +# via clang's preprocessor, not just the direct #includes in files_to_ICG.hh +# (confirmed: trick_source/er7_utils/**/io_src/ contain io_ files for headers +# nowhere directly #included). CMake's add_library() needs a static SOURCES +# list at configure time, so this uses the two-pass pattern: a build-time +# custom command runs ICG and writes a small generated .cmake file +# enumerating the real output. CMAKE_CONFIGURE_DEPENDS is set on that file +# for cache-invalidation on later header changes, but CMake only honors +# CONFIGURE_DEPENDS entries that already exist at the *configure* that +# registers them — on a truly clean tree the file doesn't exist yet, so nothing +# auto-triggers a reconfigure once the build-time custom command creates it. +# So on a clean tree this is a three-step bootstrap: +# cmake -S . -B build +# cmake --build build --target trick_io_src_gen # runs ICG, writes the list +# cmake -S . -B build && cmake --build build # reconfigure picks up the +# # real list, then builds +# Once io_src exists, ordinary `cmake --build build` reconfigures/rebuilds +# incrementally as normal (headers touch files_to_ICG.hh's mtime via +# CMAKE_CONFIGURE_DEPENDS below, which DOES work once the file is on disk). + +set(TRICK_IO_SRC_DIR ${CMAKE_BINARY_DIR}/io_src) +set(TRICK_IO_SRC_LIST_FILE ${TRICK_IO_SRC_DIR}/.generated_sources.cmake) + +# Conservative net (R7): a glob of every header ICG might transitively pull +# in. This does two distinct jobs, both needed: +# - Passed to the custom command's DEPENDS below, so a *content* edit to any +# header already in this set (e.g. adding a checkpointable member to +# include/trick/Executive.hh) touches its mtime and makes the *next* +# `cmake --build` (no reconfigure needed) re-run trick-ICG and regenerate +# the stale io_*.cpp — this is the half that actually matters day to day. +# - CONFIGURE_DEPENDS additionally forces a reconfigure when the *set* of +# matching files changes (a header added/removed), so newly-created +# headers get picked up too. +# It does not need to be an exact dependency list — same tradeoff as ICG's +# own conservative header-set discovery — but it must actually be used +# somewhere to do anything at all. +file(GLOB_RECURSE _tr_all_trick_headers CONFIGURE_DEPENDS + ${CMAKE_SOURCE_DIR}/include/trick/*.h + ${CMAKE_SOURCE_DIR}/include/trick/*.hh + ${CMAKE_SOURCE_DIR}/trick_source/er7_utils/*.hh +) + +# ── Flags mirroring TRICK_SYSTEM_CXXFLAGS / TRICK_CXXFLAGS (Makefile.common:98-197) ── +set(_tr_icg_flags + -I${CMAKE_SOURCE_DIR}/trick_source + -I${CMAKE_SOURCE_DIR}/include + -I${CMAKE_SOURCE_DIR}/include/trick/compat + -DTRICK_VER=${TRICK_MAJOR} + -DTRICK_MINOR=${TRICK_MINOR} + -fpic + ${UDUNITS_INCLUDES} + -std=c++17 +) +if(TRICK_USE_ER7_UTILS) + list(APPEND _tr_icg_flags -DUSE_ER7_UTILS_INTEGRATORS) + if(EXISTS ${CMAKE_SOURCE_DIR}/trick_source/er7_utils/CheckpointHelper) + list(APPEND _tr_icg_flags -DUSE_ER7_UTILS_CHECKPOINTHELPER) + endif() +endif() +if(TRICK_FORCE_32BIT) + list(APPEND _tr_icg_flags -m32) +endif() +# GSL: Makefile.common:147-159 puts -D_HAVE_GSL on TRICK_SYSTEM_CXXFLAGS +# whenever GSL_HOME is set (the make ICG pass inherits it), and only adds the +# -I when GSL_HOME is neither /usr nor /usr/local (both already on the +# compiler's default include path). +if(GSL_HOME) + list(APPEND _tr_icg_flags -D_HAVE_GSL) + if(NOT GSL_HOME STREQUAL "/usr" AND NOT GSL_HOME STREQUAL "/usr/local") + list(APPEND _tr_icg_flags -I${GSL_HOME}/include) + endif() +endif() +# Gate on USE_CIVETWEB/CIVETWEB_HOME (what TrickPrograms.cmake resolved +# detection to), not the raw TRICK_CIVETWEB_HOME cache option: civetweb.h at +# /usr auto-detects to USE_CIVETWEB=1 with TRICK_CIVETWEB_HOME unset, and the +# make build's ICG pass gets -DUSE_CIVETWEB via TRICK_SYSTEM_CXXFLAGS in that +# case too (Makefile.common:162-167) — files_to_ICG.hh has an +# #ifdef USE_CIVETWEB block, so a mismatch silently drops the civetweb +# io_*.cpp from libtrick.a. +if(USE_CIVETWEB) + list(APPEND _tr_icg_flags -I${CIVETWEB_HOME}/include -DUSE_CIVETWEB) +endif() + +file(MAKE_DIRECTORY ${TRICK_IO_SRC_DIR}) + +# Makefile.common:167 also adds CIVETWEB_HOME to TRICK_SYSTEM_ICG_EXCLUDE +# (exported at :72), keeping ICG out of civetweb's own headers. +set(_tr_icg_env TRICK_HOME=${CMAKE_SOURCE_DIR} TRICK_EXCLUDE=:${UDUNITS_EXCLUDE}) +if(USE_CIVETWEB) + list(APPEND _tr_icg_env TRICK_SYSTEM_ICG_EXCLUDE=${CIVETWEB_HOME}) +endif() + +add_custom_command( + OUTPUT ${TRICK_IO_SRC_LIST_FILE} + COMMAND ${CMAKE_COMMAND} -E env ${_tr_icg_env} + $ -force -sim_services -m ${_tr_icg_flags} + -o ${TRICK_IO_SRC_DIR} + ${CMAKE_SOURCE_DIR}/include/trick/files_to_ICG.hh + COMMAND ${CMAKE_COMMAND} + -DIO_SRC_DIR=${TRICK_IO_SRC_DIR} + -DER7_UTILS_SRC_DIR=${CMAKE_SOURCE_DIR}/trick_source/er7_utils + -DOUTPUT_FILE=${TRICK_IO_SRC_LIST_FILE} + -P ${CMAKE_SOURCE_DIR}/cmake/scripts/GenerateIOSrcList.cmake + WORKING_DIRECTORY ${TRICK_IO_SRC_DIR} + DEPENDS trick-ICG ${CMAKE_SOURCE_DIR}/include/trick/files_to_ICG.hh ${_tr_all_trick_headers} + COMMENT "Running trick-ICG over Trick core headers (-sim_services)" + VERBATIM +) +add_custom_target(trick_io_src_gen DEPENDS ${TRICK_IO_SRC_LIST_FILE}) + +if(EXISTS ${TRICK_IO_SRC_LIST_FILE}) + include(${TRICK_IO_SRC_LIST_FILE}) +else() + set(TRICK_IO_SOURCES "") + set(ER7_IO_SOURCES "") + message(WARNING + "io_src has not been generated yet. Run " + "`cmake --build ${CMAKE_BINARY_DIR} --target trick_io_src_gen`, then " + "re-run `cmake -S ${CMAKE_SOURCE_DIR} -B ${CMAKE_BINARY_DIR}` and " + "`cmake --build ${CMAKE_BINARY_DIR}` again so libtrick.a/" + "liber7_utils.a pick up the generated sources (see cmake/TrickICG.cmake).") +endif() +# Re-run configure automatically once trick_io_src_gen produces a fresh list. +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${TRICK_IO_SRC_LIST_FILE}) diff --git a/cmake/TrickInstall.cmake b/cmake/TrickInstall.cmake new file mode 100644 index 000000000..e31b8ab0e --- /dev/null +++ b/cmake/TrickInstall.cmake @@ -0,0 +1,132 @@ +# Phase 3 — install rules that assemble a working TRICK_HOME. +# +# The installed tree is the real product (D2/D3): sims are built by make against +# it, forever. Do NOT trust the top-level Makefile's `install` target as a spec — +# it is unmaintained and possibly broken. The authority is "what trick-CP needs to +# build and run a sim against the prefix" (Part E rule 4). The source tree is +# already TRICK_HOME-shaped (D3), so the install reproduces its bin/ include/ +# libexec/ share/ layout plus the built archives and the *generated* config_user.mk +# and swig *.py wrappers — never the copies a prior make/configure left in-source. + +# ── D6: library subdir (lib64 iff redhat-release && x86_64 && !32bit; else lib; +# Darwin always lib) — mirror config_Linux.mk exactly, do NOT use +# GNUInstallDirs (the perl flow hardcodes lib/lib64 discovery). +if(TRICK_FORCE_32BIT) + set(TRICK_LIB_SUBDIR lib) +elseif(NOT APPLE AND EXISTS "/etc/redhat-release" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(TRICK_LIB_SUBDIR lib64) +else() + set(TRICK_LIB_SUBDIR lib) +endif() +message(STATUS "Trick library subdir: ${TRICK_LIB_SUBDIR}") + +# ── Static archives → ${TRICK_LIB_SUBDIR} (the A3 nine + var_binary_parser). +set(TRICK_INSTALL_ARCHIVES + trick + trick_mm + trick_comm + trick_connection_handlers + trick_math + trick_optimization + trick_units + trick_var_binary_parser + trick_pyip +) +if(TRICK_USE_ER7_UTILS) + list(APPEND TRICK_INSTALL_ARCHIVES er7_utils) +endif() +if(USE_CIVETWEB) + list(APPEND TRICK_INSTALL_ARCHIVES trickCivet) +endif() +install(TARGETS ${TRICK_INSTALL_ARCHIVES} + ARCHIVE DESTINATION ${TRICK_LIB_SUBDIR} +) + +# ── bin/: the built trick-ICG, plus every checked-in perl driver. USE_SOURCE_ +# PERMISSIONS keeps the +x bit. trick-ICG is excluded from the source +# copy because the build target supplies it (a stale in-source binary +# may be present on a dev tree). +install(TARGETS trick-ICG RUNTIME DESTINATION bin) +install(DIRECTORY ${CMAKE_SOURCE_DIR}/bin/ + DESTINATION bin + USE_SOURCE_PERMISSIONS + PATTERN "trick-ICG" EXCLUDE +) + +# ── include/: Trick headers (incl. compat) verbatim; er7_utils headers rehomed +# from trick_source/er7_utils/**/*.hh to include/er7_utils/... . +install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/trick DESTINATION include) +if(TRICK_USE_ER7_UTILS) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/trick_source/er7_utils/ + DESTINATION include/er7_utils + FILES_MATCHING PATTERN "*.hh" + ) +endif() + +# ── libexec/trick: perl helpers (configuration_processor, make_makefile_*, pm/, +# ...) verbatim. +install(DIRECTORY ${CMAKE_SOURCE_DIR}/libexec/trick + DESTINATION libexec + USE_SOURCE_PERMISSIONS +) + +# ── libexec/trick/java/build: Trick's Java GUI jars, built to the build tree +# by trick_source/java/CMakeLists.txt (D3 — never written into source). +if(TRICK_USE_JAVA) + install(DIRECTORY ${CMAKE_BINARY_DIR}/libexec/trick/java/build/ + DESTINATION libexec/trick/java/build + FILES_MATCHING PATTERN "*.jar" + ) +endif() + +# ── share/trick: static content from source (makefiles, sim_objects, pymods, +# trickops, swig *.i and the checked-in *.py, ...). Exclude the generated +# artifacts so a dirty dev tree can't ship stale copies — the build-tree +# versions are installed just below. config_user.mk is generated by +# configure/CMake; the generated swig wrappers are sim_services/swig_*.py. +install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/trick/ + DESTINATION share/trick + USE_SOURCE_PERMISSIONS + PATTERN "config_user.mk" EXCLUDE + PATTERN "sim_services.py" EXCLUDE + PATTERN "swig_double.py" EXCLUDE + PATTERN "swig_int.py" EXCLUDE + PATTERN "swig_ref.py" EXCLUDE +) +# Generated config_user.mk (D4 parity contract) and swig wrappers, from the build +# tree. The swig *.py are add_custom_command side effects (not a target output), +# so they are globbed at install time — they exist once the build has run. +install(FILES ${CMAKE_BINARY_DIR}/share/trick/makefiles/config_user.mk + DESTINATION share/trick/makefiles +) +install(DIRECTORY ${CMAKE_BINARY_DIR}/share/trick/swig/ + DESTINATION share/trick/swig + FILES_MATCHING PATTERN "*.py" +) + +# ── share/man, share/doc: man pages and any prebuilt docs (best-effort). +install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/man DESTINATION share) +if(EXISTS ${CMAKE_SOURCE_DIR}/share/doc) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/doc DESTINATION share) +endif() + +# ── stage target: `cmake --build build --target stage` gives a runnable TRICK_HOME +# at ${CMAKE_BINARY_DIR}/stage for sim-flow validation and CTest (D3). It depends +# on the build targets so the install always reflects a fresh build. +set(TRICK_STAGE_DIR ${CMAKE_BINARY_DIR}/stage) +add_custom_target(stage + COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix ${TRICK_STAGE_DIR} + COMMENT "Staging a runnable TRICK_HOME into ${TRICK_STAGE_DIR}" + VERBATIM +) +add_dependencies(stage + ${TRICK_INSTALL_ARCHIVES} + trick-ICG + trick_io_src_gen +) +if(TRICK_USE_JAVA) + add_dependencies(stage trick-java) +endif() +if(TRICK_BUILD_DP) + add_dependencies(stage trick-data-products) +endif() diff --git a/cmake/TrickPrograms.cmake b/cmake/TrickPrograms.cmake new file mode 100644 index 000000000..b79b9a9ee --- /dev/null +++ b/cmake/TrickPrograms.cmake @@ -0,0 +1,237 @@ +# Program/library detection mirroring autoconf/configure.ac's non-LLVM, +# non-Python checks (tee, ld, flex, bison, curl, zip, gnuplot, swig, perl + +# modules, zlib, libxml2, threads, X11/Motif, java/maven) plus the small +# "other optional command line arguments" cluster (HDF5, GSL, civetweb). +# See autoconf/configure.ac and autoconf/m4/tr_*.m4 for the macros this +# replicates. + +# ── Required simple tools (autoconf/configure.ac:111-124) ───────────────── +find_program(TEE_EXECUTABLE tee) +if(NOT TEE_EXECUTABLE) + message(FATAL_ERROR "could not find tee") +endif() + +find_program(LD_EXECUTABLE ld) +if(NOT LD_EXECUTABLE) + message(FATAL_ERROR "could not find ld") +endif() + +find_program(CURL_EXECUTABLE curl) +if(NOT CURL_EXECUTABLE) + message(FATAL_ERROR "could not find curl") +endif() + +find_program(ZIP_EXECUTABLE zip) +if(NOT ZIP_EXECUTABLE) + message(FATAL_ERROR "Trick now requires zip but it could not be found. Please install zip. We recommend you use your OS package manager") +endif() + +find_program(GNUPLOT_EXECUTABLE gnuplot) +if(NOT GNUPLOT_EXECUTABLE) + message(NOTICE "could not find gnuplot") +endif() + +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) +# AC_PROG_LEX([noyywrap]) (unlike AC_PATH_PROG(BISON,...)) stores the bare +# program name it matched, not a resolved path — match that exactly. +get_filename_component(FLEX_EXECUTABLE_NAME "${FLEX_EXECUTABLE}" NAME) + +# ── Perl >= 5.14 + required modules (autoconf/configure.ac:121-122,195-196) ─ +find_package(Perl 5.14 REQUIRED) +execute_process( + COMMAND ${PERL_EXECUTABLE} -MText::Balanced -e 1 + RESULT_VARIABLE _tr_perl_text_balanced + OUTPUT_QUIET ERROR_QUIET +) +if(NOT _tr_perl_text_balanced EQUAL 0) + message(FATAL_ERROR "could not find perl modules Text::Balanced") +endif() +execute_process( + COMMAND ${PERL_EXECUTABLE} -MDigest::MD5 -e 1 + RESULT_VARIABLE _tr_perl_digest_md5 + OUTPUT_QUIET ERROR_QUIET +) +if(NOT _tr_perl_digest_md5 EQUAL 0) + message(FATAL_ERROR "could not find perl module Digest::MD5") +endif() + +# ── SWIG >= 3.0 (autoconf/m4/tr_swig_bin.m4) ─────────────────────────────── +# tr_swig_bin.m4 -> AX_PKG_SWIG -> AC_PATH_PROG([SWIG], [swig]) only ever +# searches for the bare name "swig". find_package(SWIG)'s own executable +# search can instead land on a version-suffixed binary (e.g. swig4.0) when +# both exist on PATH, which mismatches config_user.mk's SWIG value even +# though the version requirement is equally satisfied either way. +find_program(SWIG_EXECUTABLE NAMES swig) +if(NOT SWIG_EXECUTABLE) + message(FATAL_ERROR "could not find swig") +endif() +execute_process( + COMMAND ${SWIG_EXECUTABLE} -version + OUTPUT_VARIABLE _tr_swig_version_output + OUTPUT_STRIP_TRAILING_WHITESPACE +) +string(REGEX MATCH "SWIG Version ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${_tr_swig_version_output}") +if(NOT CMAKE_MATCH_1 OR CMAKE_MATCH_1 VERSION_LESS "3.0") + message(FATAL_ERROR "Trick requires SWIG version >= 3.0, found: ${CMAKE_MATCH_1}") +endif() +set(SWIG_VERSION "${CMAKE_MATCH_1}") + +# ── zlib / libxml2 / threads ─────────────────────────────────────────────── +find_package(ZLIB REQUIRED) + +find_package(LibXml2 REQUIRED) +# AC_CHECK_LIB(xml2, main, ...) renders the literal flag, not a resolved path. +set(LIBXML "-lxml2") + +find_package(Threads REQUIRED) +set(PTHREAD_CFLAGS "-pthread") +# AX_PTHREAD renders "-lpthread" on every Unix Trick supports, including +# Darwin (where CMAKE_THREAD_LIBS_INIT is empty because pthread symbols live +# in libSystem) — match its literal output rather than CMake's. +set(PTHREAD_LIBS "-lpthread") + +# ── X11 / Motif (autoconf/m4/tr_xwindows.m4, tr_jsc_dirs.m4) ─────────────── +find_package(X11) +if(X11_FOUND) + set(USE_X_WINDOWS 1) + set(_tr_x11_libdir "") + if(X11_LIBRARY_DIRS) + set(_tr_x11_libdir "${X11_LIBRARY_DIRS}") + elseif(X11_X11_LIB) + get_filename_component(_tr_x11_libdir "${X11_X11_LIB}" DIRECTORY) + endif() + # AC_PATH_XTRA (tr_xwindows.m4:12) only sets X_LIB_DIR when $x_libraries + # is non-empty, which autoconf itself leaves empty whenever the compiler + # already finds X11 on its default library search path (the common case + # on Linux distros and Homebrew, where X11 libs live in + # /usr/lib/, /usr/lib64, or /opt/homebrew/lib alongside + # everything else). CMake's FindX11 always returns an absolute dir + # regardless, so replicate autoconf's "only if nonstandard" behavior by + # checking against the compiler's own implicit link directories. + set(X_LIB_DIR "") + if(_tr_x11_libdir AND NOT _tr_x11_libdir IN_LIST CMAKE_C_IMPLICIT_LINK_DIRECTORIES) + set(X_LIB_DIR "-L${_tr_x11_libdir}") + endif() + if(NOT X11_Xt_FOUND) + message(FATAL_ERROR "could not find libxt development headers") + endif() + + # Motif is only required when the fermi-ware data_products tree exists. + set(MOTIF_HOME "") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/trick_source/data_products/fermi-ware") + if(EXISTS "/usr/include/Xm/Xm.h") + set(MOTIF_HOME "/usr") + elseif(EXISTS "/usr/local/include/Xm/Xm.h") + set(MOTIF_HOME "/usr/local") + elseif(EXISTS "/opt/homebrew/include/Xm/Xm.h") + set(MOTIF_HOME "/opt/homebrew") + else() + message(FATAL_ERROR "could not find Xm/Xm.h") + endif() + endif() +else() + set(USE_X_WINDOWS 0) + set(X_LIB_DIR "") + set(MOTIF_HOME "") +endif() + +# ── Java / Maven (autoconf/m4/tr_java.m4), gated by TRICK_USE_JAVA ───────── +if(TRICK_USE_JAVA) + set(USE_JAVA 1) + find_package(Java 1.8 COMPONENTS Development REQUIRED) + # AX_PROG_JAVA_CC(javac) only verifies "javac" is on PATH and stores the + # literal candidate name, not a resolved path — match that exactly + # rather than substituting Java_JAVAC_EXECUTABLE's absolute path. + set(Java_JAVAC_EXECUTABLE "javac") + if(NOT TRICK_OFFLINE) + find_program(MVN_EXECUTABLE mvn) + if(NOT MVN_EXECUTABLE) + message(FATAL_ERROR "could not find maven") + endif() + else() + set(MVN_EXECUTABLE "") + endif() +else() + set(USE_JAVA 0) + set(Java_JAVAC_EXECUTABLE "") + set(MVN_EXECUTABLE "") +endif() + +# ── HDF5 (autoconf/m4/tr_hdf5_home.m4) ────────────────────────────────────── +if(HDF5_HOME) + if(NOT EXISTS "${HDF5_HOME}/include/hdf5.h") + message(FATAL_ERROR "could not find ${HDF5_HOME}/include/hdf5.h") + endif() +elseif(EXISTS "/usr/include/hdf5.h") + set(HDF5_HOME "/usr") +elseif(EXISTS "/opt/homebrew/include/hdf5.h") + set(HDF5_HOME "/opt/homebrew") +else() + set(HDF5_HOME "") +endif() + +# trick::hdf5: derived from HDF5_HOME (not find_package(HDF5), which can +# resolve a different install than the ladder above — e.g. via HDF5_ROOT or +# pkg-config — and silently diverge from the HDF5_HOME baked into +# config_user.mk for sims). Mirrors the make build's literal link line +# (-L$(HDF5_HOME)/lib -lhdf5_hl -lhdf5 -lsz); -lsz has no FindHDF5 equivalent. +# No -DHDF5 here: that define is deliberately per-file/per-target scoped to +# match the Makefiles (see sim_services/CMakeLists.txt, data_products/Log). +if(HDF5_HOME) + add_library(trick::hdf5 INTERFACE IMPORTED) + target_link_directories(trick::hdf5 INTERFACE ${HDF5_HOME}/lib) + target_link_libraries(trick::hdf5 INTERFACE hdf5_hl hdf5 sz) + if(NOT HDF5_HOME STREQUAL "/usr") + target_include_directories(trick::hdf5 INTERFACE ${HDF5_HOME}/include) + endif() +endif() + +# ── GSL (autoconf/m4/tr_gsl_home.m4) ──────────────────────────────────────── +if(GSL_HOME) + if(NOT EXISTS "${GSL_HOME}/include/gsl") + message(FATAL_ERROR "could not find ${GSL_HOME}/include/gsl") + endif() +elseif(EXISTS "/usr/include/gsl/gsl_rng.h") + set(GSL_HOME "/usr") +elseif(EXISTS "/opt/homebrew/include/gsl/gsl_rng.h") + set(GSL_HOME "/opt/homebrew") +else() + set(GSL_HOME "") +endif() + +# ── civetweb (autoconf/m4/tr_civetweb_home.m4), gated by TRICK_CIVETWEB_HOME ─ +if(TRICK_CIVETWEB_HOME) + if(NOT EXISTS "${TRICK_CIVETWEB_HOME}/include/civetweb.h" OR + NOT EXISTS "${TRICK_CIVETWEB_HOME}/lib/libcivetweb.a") + message(FATAL_ERROR "Could not find all of the civetweb files.") + endif() + set(CIVETWEB_HOME "${TRICK_CIVETWEB_HOME}") + set(USE_CIVETWEB 1) +elseif(EXISTS "/usr/include/civetweb.h") + set(CIVETWEB_HOME "/usr") + set(USE_CIVETWEB 1) +else() + set(CIVETWEB_HOME "") + set(USE_CIVETWEB 0) +endif() + +# ── er7_utils, default enabled (autoconf/m4/tr_er7_utils.m4) ─────────────── +option(TRICK_USE_ER7_UTILS "use er7_utils" ON) +if(TRICK_USE_ER7_UTILS) + set(USE_ER7_UTILS 1) +else() + set(USE_ER7_UTILS 0) +endif() + +# ── Compiler full paths (autoconf/configure.ac:108-109) ──────────────────── +# CMAKE_C/CXX_COMPILER are already resolved to absolute paths by CMake. +set(CC "${CMAKE_C_COMPILER}") +set(CXX "${CMAKE_CXX_COMPILER}") + +# ── GCC version (autoconf/m4/tr_gcc_version.m4), empty for clang/mac ─────── +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(GCC_VERSION "${CMAKE_CXX_COMPILER_VERSION}") +else() + set(GCC_VERSION "") +endif() diff --git a/cmake/TrickPython.cmake b/cmake/TrickPython.cmake new file mode 100644 index 000000000..444251b28 --- /dev/null +++ b/cmake/TrickPython.cmake @@ -0,0 +1,63 @@ +# Python detection for config_user.mk (D5): capture literal python-config +# output strings rather than relying on find_package(Python3) values, since +# sims' historical link lines include platform extras that Python3_LIBRARIES +# does not reproduce. Mirrors autoconf/configure.ac:127-187 exactly, +# including search order and the `--embed` / newline-stripping behavior. +# +# Honors the PYTHON_VERSION cache variable (e.g. "3" looks for python3), +# equivalent to configure's PYTHON_VERSION influential env var. +# +# Exports: PYTHON, PYTHON_CONFIG, PYTHON_CPPFLAGS, PYTHON_LIBS + +find_program(PYTHON + NAMES python${PYTHON_VERSION} python python3 +) +if(NOT PYTHON) + message(FATAL_ERROR "could not find python python or python3. Please install the python development package") +endif() + +execute_process( + COMMAND ${PYTHON} -c "import sys; print(str(sys.version_info[0])+\".\"+str(sys.version_info[1]))" + OUTPUT_VARIABLE PYTHON_MAJORMINOR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +execute_process( + COMMAND ${PYTHON} -c "import sys; print(str(sys.version_info[0]))" + OUTPUT_VARIABLE PYTHON_MAJOR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +find_program(PYTHON_CONFIG + NAMES python${PYTHON_MAJORMINOR}-config python${PYTHON_MAJOR}-config python${PYTHON_VERSION}-config python-config +) +if(NOT PYTHON_CONFIG) + message(FATAL_ERROR "could not find python-config python-config or python-config. Please install the python development package") +endif() + +set(_tr_python_libs_command --ldflags --libs) +if(NOT PYTHON_MAJORMINOR VERSION_LESS "3.8") + list(APPEND _tr_python_libs_command --embed) +endif() + +execute_process( + COMMAND ${PYTHON_CONFIG} --includes + OUTPUT_VARIABLE PYTHON_CPPFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE +) +string(REPLACE "-I" "-isystem" PYTHON_CPPFLAGS "${PYTHON_CPPFLAGS}") + +execute_process( + COMMAND ${PYTHON_CONFIG} ${_tr_python_libs_command} + OUTPUT_VARIABLE PYTHON_LIBS +) +# configure.ac only does `tr '\r\n' ' '` on python-config's raw output — no +# further stripping — so a leading/trailing space python-config itself emits +# is preserved in config_user.mk. Don't string(STRIP ...) here: it produced a +# byte-for-byte parity mismatch against autoconf's output on RHEL-family +# pythons (see test/build_config/compare_config_user.sh CI failures). +string(REPLACE "\r" " " PYTHON_LIBS "${PYTHON_LIBS}") +string(REPLACE "\n" " " PYTHON_LIBS "${PYTHON_LIBS}") + +# Always empty today (see A1) — kept as a named, substituted variable for +# parity with config_user.mk.in's contract. +set(PYTHON_EXTRA_LIBS "") diff --git a/cmake/TrickTest.cmake b/cmake/TrickTest.cmake new file mode 100644 index 000000000..825fc46b3 --- /dev/null +++ b/cmake/TrickTest.cmake @@ -0,0 +1,146 @@ +# Phase 3 — CTest wiring. +# +# Two kinds of tests, both run against a staged TRICK_HOME (never the source tree, +# never a make build): +# +# LABEL unit — the per-directory gtest suites under trick_source/**/test. Each +# has a hand-written Makefile that `include`s Makefile.common; that +# file force-computes TRICK_HOME from its own location, but the +# assignment is plain (not `override`), so a `make TRICK_HOME=` +# command-line override wins and redirects config_user.mk, the +# archives (TRICK_LIB_DIR), headers, and trick-ICG to the stage. +# +# LABEL sims — the universal acceptance test: trick-CP builds and runs real sims +# against the stage. The sole test carrying this label is `sims` — the +# full ~52-sim test_sims.yml suite via trickops.py, the same one +# `make sim_test` runs. It replaced the earlier two-sim smoke subset; +# there is no lighter-weight sims test anymore. It requires the +# trickops Python deps (share/trick/trickops/requirements.txt) to be +# installed by the caller. +# +# A CTest fixture stages the install first (cmake --install into ${TRICK_STAGE_DIR}), +# so `ctest` works after a plain `cmake --build`. The build itself must be complete +# before ctest — ctest does not compile the archives. + +include(CTest) + +if(NOT BUILD_TESTING) + return() +endif() + +if(NOT DEFINED TRICK_STAGE_DIR) + set(TRICK_STAGE_DIR ${CMAKE_BINARY_DIR}/stage) +endif() + +# ── Setup fixture: install the build tree into the stage prefix. +add_test(NAME stage_install + COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix ${TRICK_STAGE_DIR} +) +set_tests_properties(stage_install PROPERTIES FIXTURES_SETUP trick_stage) + +# ── Unit tests: mirror the top-level Makefile's UNIT_TEST_DIRS (sim_services/*/test +# and trick_utils/*/test), with the same %Integrator/test filter — conditional on +# USE_ER7_UTILS, exactly like Makefile:136-138 (`ifeq ($(USE_ER7_UTILS), 0)`), not +# unconditional. This checkout defaults TRICK_USE_ER7_UTILS=ON, so Integrator/test +# is normally INCLUDED, matching `make unit_test`'s real dir count. +file(GLOB _tr_unit_test_dirs + ${CMAKE_SOURCE_DIR}/trick_source/sim_services/*/test + ${CMAKE_SOURCE_DIR}/trick_source/trick_utils/*/test +) +foreach(_dir ${_tr_unit_test_dirs}) + if(NOT EXISTS ${_dir}/Makefile) + continue() + endif() + if(NOT TRICK_USE_ER7_UTILS AND _dir MATCHES "Integrator/test$") + continue() # filtered out when ER7 utils are off (Makefile:136-138) + endif() + # ut_, e.g. ut_MemoryManager + get_filename_component(_parent ${_dir} DIRECTORY) + get_filename_component(_name ${_parent} NAME) + add_test(NAME ut_${_name} + COMMAND make -C ${_dir} test TRICK_HOME=${TRICK_STAGE_DIR} + ) + set_tests_properties(ut_${_name} PROPERTIES + LABELS unit + FIXTURES_REQUIRED trick_stage + TIMEOUT 900 + ) +endforeach() + +# ── DPX (data_products) unit tests: same LABEL unit as above, but its own +# makefile needs extra overrides (see that makefile's header comment) +# because CMake builds each data_products library into its own target +# output directory instead of one shared lib_/ dir. TRICK_SRC_HOME +# keeps headers resolving against the real source tree even though +# TRICK_HOME below is the staged install. +if(TRICK_BUILD_DP) + set(_tr_dpx_unit_test_dir ${CMAKE_SOURCE_DIR}/trick_source/data_products/DPX/test/unit_test) + if(EXISTS ${_tr_dpx_unit_test_dir}/makefile) + add_test(NAME ut_DataProducts + COMMAND make -C ${_tr_dpx_unit_test_dir} test + TRICK_HOME=${TRICK_STAGE_DIR} + TRICK_SRC_HOME=${CMAKE_SOURCE_DIR} + LIB_LOG_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/Log + LIB_VAR_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/Var + LIB_EQPARSE_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/EQParse + LIB_UNITS_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/units + LIB_DPM_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/DPX/DPM + LIB_DPC_DIR=${CMAKE_BINARY_DIR}/trick_source/data_products/DPX/DPC + ) + set_tests_properties(ut_DataProducts PROPERTIES + LABELS unit + FIXTURES_REQUIRED trick_stage + TIMEOUT 900 + ) + endif() +endif() + +# ── Java unit tests (JUnit, via `mvn test`). Unlike the C++ gtest suites, Maven +# resolves everything relative to trick_source/java itself, so no TRICK_HOME +# path-shape juggling is needed; -Dcmake=false matches the top-level +# Makefile's `test:` target (Makefile in trick_source/java) and writes +# surefire reports/compiled test classes under libexec/trick/java/build in +# the source tree — test output, not a product-build write (D3 is about the +# product build, same class of exception already noted for the C++ gtest +# suites' own **/test artifacts). +# MVN_EXECUTABLE is empty under TRICK_OFFLINE (offline jars are prebuilt +# copies; maven isn't required or detected), so gate on it too rather than +# registering a test with an empty command. +if(TRICK_USE_JAVA AND MVN_EXECUTABLE) + add_test(NAME ut_java + COMMAND ${MVN_EXECUTABLE} test -Dcmake=false -Dmaven.wagon.http.retryHandler.count=15 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/trick_source/java + ) + set_tests_properties(ut_java PROPERTIES + LABELS unit + TIMEOUT 900 + ) +endif() + +# ── Full sim suite (LABEL sims): the same trickops.py/test_sims.yml suite +# `make sim_test` runs (test_overrides.mk), covering all ~52 sims in +# test_sims.yml. This is now the *only* sims-acceptance test — it replaced the +# earlier two-sim smoke subset (sim_demo_sdefine/sim_stls via +# test/build_config/run_sim_flow.sh), which exercised the identical trick-CP -> +# ICG -> SWIG -> compile -> run path as a strict subset of what this suite +# already covers. run_sim_flow.sh itself is left in place for ad hoc manual +# single-sim verification (Part E rule 4); it's just no longer wired into CTest. +# trickops.py's --trick_dir (added alongside this CTest wiring) points +# build_cmd at /bin/trick-CP, which self-derives TRICK_HOME from its own +# location (bin/trick-CP:13, dirname($trick_bin)) — no TRICK_HOME env needed. +# --trick_top_level stays the source tree, since the test/SIM_* sim +# directories test_sims.yml references only exist there, not in the stage. +if(EXISTS ${CMAKE_SOURCE_DIR}/test_sims.yml) + add_test(NAME sims + COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/trickops.py + --trick_top_level ${CMAKE_SOURCE_DIR} + --trick_dir ${TRICK_STAGE_DIR} + --config_file test_sims.yml + --quiet + ) + set_tests_properties(sims PROPERTIES + LABELS sims + FIXTURES_REQUIRED trick_stage + TIMEOUT 3600 + ) +endif() diff --git a/cmake/scripts/GenerateIOSrcList.cmake b/cmake/scripts/GenerateIOSrcList.cmake new file mode 100644 index 000000000..ae8824d60 --- /dev/null +++ b/cmake/scripts/GenerateIOSrcList.cmake @@ -0,0 +1,50 @@ +# Run in `cmake -P` script mode after a trick-ICG -sim_services run has +# populated IO_SRC_DIR with a flat set of io_.cpp files (plus +# class_map.cpp). Partitions that flat list into TRICK_IO_SOURCES (bundled +# into libtrick.a) and ER7_IO_SOURCES (bundled into liber7_utils.a), matching +# the historical split PrintAttributes::createIOFileName performs by +# inspecting each header's source path — a distinction lost once ICG is +# invoked with an explicit `-o` (see CMAKE_MIGRATION_PLAN.md Part C, Phase 2 +# risk R1/R7 write-up). Reconstructed here by checking whether a header with +# a matching basename exists anywhere under ER7_UTILS_SRC_DIR; basenames are +# verified unique across the whole tree (no collisions as of this writing). +# +# Required -D arguments: IO_SRC_DIR, ER7_UTILS_SRC_DIR, OUTPUT_FILE + +if(NOT IO_SRC_DIR OR NOT ER7_UTILS_SRC_DIR OR NOT OUTPUT_FILE) + message(FATAL_ERROR "GenerateIOSrcList.cmake requires -DIO_SRC_DIR=, -DER7_UTILS_SRC_DIR=, -DOUTPUT_FILE=") +endif() + +file(GLOB _tr_io_files "${IO_SRC_DIR}/io_*.cpp") +file(GLOB_RECURSE _tr_er7_headers "${ER7_UTILS_SRC_DIR}/*.hh" "${ER7_UTILS_SRC_DIR}/*.h") + +set(_tr_er7_basenames) +foreach(_hdr ${_tr_er7_headers}) + get_filename_component(_stem "${_hdr}" NAME_WE) + list(APPEND _tr_er7_basenames "${_stem}") +endforeach() + +set(_tr_trick_io_sources) +set(_tr_er7_io_sources) +foreach(_cpp ${_tr_io_files}) + get_filename_component(_name "${_cpp}" NAME_WE) + # NOT string(REGEX REPLACE "^io_" ...): CMake's regex replace strips + # repeated leading matches (e.g. turns "io_io_alloc" into "alloc" instead + # of "io_alloc"), silently misrouting io_io_alloc.cpp (from + # include/trick/io_alloc.h) into the er7_utils archive. Every io_*.cpp + # name has exactly one "io_" prefix by construction (PrintAttributes.cpp: + # base_name = "io_" + stem), so a plain substring removal is correct. + string(SUBSTRING "${_name}" 3 -1 _stem) + list(FIND _tr_er7_basenames "${_stem}" _tr_idx) + if(_tr_idx GREATER -1) + list(APPEND _tr_er7_io_sources "${_cpp}") + else() + list(APPEND _tr_trick_io_sources "${_cpp}") + endif() +endforeach() + +file(WRITE "${OUTPUT_FILE}" +"# Auto-generated by GenerateIOSrcList.cmake — do not edit. +set(TRICK_IO_SOURCES ${_tr_trick_io_sources} \"${IO_SRC_DIR}/class_map.cpp\") +set(ER7_IO_SOURCES ${_tr_er7_io_sources}) +") diff --git a/share/trick/makefiles/Makefile.common b/share/trick/makefiles/Makefile.common index 4db13de63..ead94fd04 100644 --- a/share/trick/makefiles/Makefile.common +++ b/share/trick/makefiles/Makefile.common @@ -106,16 +106,6 @@ ifeq ($(HAVE_ZEROCONF),1) TRICK_SYSTEM_CXXFLAGS += -DHAVE_ZEROCONF endif -ifeq ($(USE_ER7_UTILS),ON) - ER7_UTILS_HOME := $(TRICK_HOME)/trick_source/er7_utils - TRICK_SYSTEM_CXXFLAGS += -DUSE_ER7_UTILS_INTEGRATORS - TRICK_LIBS += -ler7_utils - ifneq ($(wildcard ${ER7_UTILS_HOME}/CheckpointHelper),) - USE_ER7_UTILS_CHECKPOINTHELPER = 1 - TRICK_SYSTEM_CXXFLAGS += -DUSE_ER7_UTILS_CHECKPOINTHELPER - endif -endif -# older test, remove when cmake is only build system ifeq ($(USE_ER7_UTILS), 1) ER7_UTILS_HOME := $(TRICK_HOME)/trick_source/er7_utils TRICK_SYSTEM_CXXFLAGS += -DUSE_ER7_UTILS_INTEGRATORS @@ -126,13 +116,6 @@ ifeq ($(USE_ER7_UTILS), 1) endif endif -ifeq ($(TRICK_FORCE_32BIT),ON) - TRICK_ICGFLAGS += -m32 - TRICK_SYSTEM_CXXFLAGS += -m32 - TRICK_SYSTEM_LDFLAGS += -m32 - LD_PARTIAL += -melf_i386 -endif -# older test, remove when cmake is only build system ifeq ($(TRICK_FORCE_32BIT), 1) TRICK_ICGFLAGS += -m32 TRICK_SYSTEM_CXXFLAGS += -m32 diff --git a/share/trick/makefiles/config_user_cmake.mk.in b/share/trick/makefiles/config_user_cmake.mk.in index c530d27c6..3d4e2959c 100644 --- a/share/trick/makefiles/config_user_cmake.mk.in +++ b/share/trick/makefiles/config_user_cmake.mk.in @@ -1,64 +1,51 @@ -TRICK_FORCE_32BIT = @TRICK_FORCE_32BIT@ +TRICK_FORCE_32BIT = @TRICK_FORCE_32BIT_MK@ -CC = @CMAKE_C_COMPILER@ -CXX = @CMAKE_CXX_COMPILER@ -LD = @CMAKE_LINKER@ +CC = @CC@ +CXX = @CXX@ +LD = @LD_EXECUTABLE@ PERL = @PERL_EXECUTABLE@ -LEX = @FLEX_EXECUTABLE@ +LEX = @FLEX_EXECUTABLE_NAME@ YACC = @BISON_EXECUTABLE@ SWIG = @SWIG_EXECUTABLE@ -PYTHON = @PYTHON_EXECUTABLE@ +PYTHON = @PYTHON@ CLANG = @CLANG_EXECUTABLE@ TEE = @TEE_EXECUTABLE@ -TRICK_MONGOOSE = @TRICK_MONGOOSE@ +MVN = @MVN_EXECUTABLE@ + USE_JAVA = @USE_JAVA@ JAVAC = @Java_JAVAC_EXECUTABLE@ -USE_X_WINDOWS = @USE_X_WINDOWS@ - -LLVM_HOME = @LLVM_ROOT_DIR@ +TRICK_OFFLINE = @TRICK_OFFLINE_MK@ -ICG_CLANGLIBS = \ - -lclangFrontend \ - -lclangDriver \ - -lclangSerialization \ - -lclangParse \ - -lclangSema \ - -lclangAnalysis \ - -lclangEdit \ - -lclangAST \ - -lclangLex \ - -lclangBasic \ +USE_CIVETWEB = @USE_CIVETWEB@ +CIVETWEB_HOME = @CIVETWEB_HOME@ -PYTHON_INCLUDES = -isystem@PYTHON_INCLUDE_DIRS@ -PYTHON_LIB = @PYTHON_LIBRARIES@ +USE_X_WINDOWS = @USE_X_WINDOWS@ -# Only add udunits include if it is not in /usr/include. -ifneq ("@UDUNITS2_INCLUDES@","/usr/include") -UDUNITS_INCLUDES = -I@UDUNITS2_INCLUDES@ -else -UDUNITS_INCLUDES = -endif +LLVM_HOME = @LLVM_HOME@ +ICG_CLANGLIBS = @ICG_CLANGLIBS@ -UDUNITS_LDFLAGS = @UDUNITS2_LIBRARIES@ -TRICK_EXCLUDE += :@UDUNITS_EXCLUDE@ +PYTHON_INCLUDES = @PYTHON_CPPFLAGS@ +PYTHON_LIB = @PYTHON_LIBS@ @PYTHON_EXTRA_LIBS@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ -LIBXML_INCLUDES = -I@LIBXML2_INCLUDE_DIR@ -LIBXML = @LIBXML2_LIBRARIES@ +X_LIB_DIR = @X_LIB_DIR@ +MOTIF_HOME = @MOTIF_HOME@ -PTHREAD_LIBS = @CMAKE_THREAD_LIBS_INIT@ -GSL_HOME = @GSL_ROOT_DIR@ +UDUNITS_INCLUDES = @UDUNITS_INCLUDES@ +UDUNITS_LDFLAGS = @UDUNITS_LDFLAGS@ +TRICK_EXCLUDE += :@UDUNITS_EXCLUDE@ HDF5 = @HDF5_HOME@ +GSL_HOME = @GSL_HOME@ GTEST_HOME = @GTEST_HOME@ - -PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ -X_LIB_DIR = @X_LIB_DIR@ -MOTIF_HOME = @MOTIF_HOME@ +GTEST_CXXSTD = @GTEST_CXXSTD@ USE_ER7_UTILS = @USE_ER7_UTILS@ +LIBXML = @LIBXML@ -PREFIX ?= @prefix@ +PREFIX ?= @CMAKE_INSTALL_PREFIX@ +TRICK_GCC_VERSION = @GCC_VERSION@ CONFIG_MK = 1 - diff --git a/share/trick/trickops/TrickWorkflow.py b/share/trick/trickops/TrickWorkflow.py index 7941ac1f2..ab4399564 100644 --- a/share/trick/trickops/TrickWorkflow.py +++ b/share/trick/trickops/TrickWorkflow.py @@ -7,32 +7,16 @@ PyYAML # For reading input yml files psutil # For child process acquisition """ - -import copy -import hashlib -import inspect -import os -import re -import socket -import subprocess -import sys -import threading -import time - +import os, sys, threading, socket, abc, time, re, copy, subprocess, hashlib, inspect from TrickWorkflowYamlVerifier import * # TODO revisit this import - Jordan -from WorkflowCommon import * +from WorkflowCommon import * +import pprint # Import Trick natively supported python variable server utilities -sys.path.append( - os.path.abspath( - os.path.join( - os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: 0))), - "../pymods", - ) - ) -) - +sys.path.append(os.path.abspath(os.path.join(os.path.dirname( + os.path.abspath(inspect.getsourcefile(lambda:0))), '../pymods'))) from trick import variable_server +import pdb # This global is the result of hours of frustration and debugging. This is only used by doctest # but appears to be the only solution to the problem of __file__ not being an absolute path in @@ -47,10 +31,7 @@ # given for any function that prints, because we make use of color printing extensively in this # module via the tprint function, and doctest is not well suited for handling color output. # - Sincerely, a quite ornery Dan Jordan 4/2021 -this_trick = os.path.normpath( - os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../..") -) - +this_trick = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../..')) class TrickWorkflow(WorkflowCommon): """ @@ -95,14 +76,11 @@ class TrickWorkflow(WorkflowCommon): # Note that runs, comparisons, and analysis management classes and/or jobs also # support the report() method """ - # These are static so Run and Sim classes can access them when needed # TODO: It would be nice to consolidate and read this from .yaml_requirements.txt # -Jordan 12/2022 - allowed_phase_range = {"min": -1000, "max": 1000} - all_possible_phases = range( - allowed_phase_range["min"], allowed_phase_range["max"] + 1 - ) + allowed_phase_range = {'min': -1000, 'max': 1000} + all_possible_phases = range(allowed_phase_range['min'], allowed_phase_range['max']+1) def listify_phase(phase=None): """ @@ -131,28 +109,21 @@ def listify_phase(phase=None): """ # Handle type of phase given phases = [] # To be populated with all valid phases requested by user - if phase is None: + if (phase is None): phases = list(TrickWorkflow.all_possible_phases) elif isinstance(phase, int) and phase in TrickWorkflow.all_possible_phases: phases = [phase] - elif ( - (isinstance(phase, list) or isinstance(phase, range)) - and all(isinstance(p, int) for p in phase) - and all(p in TrickWorkflow.all_possible_phases for p in phase) - ): + elif ( (isinstance(phase, list) or isinstance(phase, range)) and + all(isinstance(p, int) for p in phase) and + all(p in TrickWorkflow.all_possible_phases for p in phase)): phases = list(phase) # Cast to list to cover range case else: - msg = ( - "ERROR: Given phase %s in listify_given_phase() must be an int," - " list of ints, or range() within the bounds [%s, %s]" - % ( - phase, - TrickWorkflow.allowed_phase_range["min"], - TrickWorkflow.allowed_phase_range["max"], - ) - ) + msg =("ERROR: Given phase %s in listify_given_phase() must be an int," + " list of ints, or range() within the bounds [%s, %s]" % (phase, + TrickWorkflow.allowed_phase_range['min'], + TrickWorkflow.allowed_phase_range['max'])) raise RuntimeError(msg) - return phases + return(phases) def _find_range_string(string): """ @@ -171,22 +142,18 @@ def _find_range_string(string): RuntimeError If more than one range string found """ - pattern = r"\[\d+-\d+\]" + pattern = "\[\d+-\d+\]" if (len(re.findall(pattern, string))) > 1: - msg = ( - "ERROR: [min-max] pattern found more than once in %s. Only one instance is" - " supported." % (string) - ) - raise RuntimeError(msg) + msg = ("ERROR: [min-max] pattern found more than once in %s. Only one instance is" + " supported." % (string)) + raise RuntimeError(msg) m = re.search(pattern, string) if m: - return m.group(0) + return m.group(0) else: - return None + return None - def __init__( - self, project_top_level, log_dir, trick_dir, config_file, cpus=3, quiet=False - ): + def __init__(self, project_top_level, log_dir, trick_dir, config_file, cpus=3, quiet=False): """ Initialize this instance. @@ -209,25 +176,21 @@ def __init__( when true which is useful for running in a CI system where stdin isn't available """ - super().__init__( - project_top_level=project_top_level, log_dir=log_dir, quiet=quiet - ) - self.config_errors = [] # Contains errors in setup of management classes - self.compare_errors = False # True if comparison errors were found - self.sims = [] # list of Sim() instances, filled out from config file + super().__init__(project_top_level=project_top_level, log_dir=log_dir, quiet=quiet) + self.config_errors = [] # Contains errors in setup of management classes + self.compare_errors = False # True if comparison errors were found + self.sims = [] # list of Sim() instances, filled out from config file self.config_file = config_file # path to yml config - self.cpus = cpus # Number of CPUs this workflow should use when running + self.cpus = cpus # Number of CPUs this workflow should use when running self.yaml_verifier = TrickWorkflowYamlVerifier(self.config_file) # If not found in the config file, these defaults are used self.trick_dir = trick_dir self.trick_host_cpu = self.get_trick_host_cpu() - self.env = "" + self.env = '' self.config = self.yaml_verifier.verify() - self.parsing_errors = ( - self.yaml_verifier.parsing_errors - ) # All errors found during parsing + self.parsing_errors = self.yaml_verifier.parsing_errors # All errors found during parsing for e in self.parsing_errors: - tprint(e, "DARK_RED") + tprint(e, 'DARK_RED') self._populate_sims() def _populate_sims(self): @@ -239,127 +202,87 @@ def _populate_sims(self): from self.config so we can create all management classes at the sim and run levels without worry. """ - def cprint(msg, color): self.config_errors.append(msg) tprint(msg, color) - - self.env = self.config["globals"]["env"] - all_sim_paths = [] # Keep a list of all paths for uniqueness check + self.env = self.config['globals']['env'] + all_sim_paths = [] # Keep a list of all paths for uniqueness check for s in self.config: - if not str(s).startswith("SIM"): # Ignore everything not starting with SIM - continue - if not os.path.exists( - os.path.join(self.project_top_level, self.config[s]["path"]) - ): - cprint( - "ERROR: %s's 'path' %s not found. Continuing but skipping this entire entry from %s." - % (s, self.config[s]["path"], self.config_file), - "DARK_RED", - ) - continue - if self.config[s]["path"] in all_sim_paths: - cprint( - "ERROR: %s's 'path' is not unique in %s. Continuing but ignoring this sim." - % (s, self.config_file), - "DARK_RED", - ) - continue - # Add the CPU format string (won't fail if there is no CPU placeholder) - self.config[s]["binary"] = self.config[s]["binary"].format( - cpu=self.trick_host_cpu - ) - # Add the full path to the build command - trick_CP = os.path.join(self.trick_dir, "bin/trick-CP") - if self.config[s]["build_args"]: - trick_CP += " " + self.config[s]["build_args"] - thisSim = TrickWorkflow.Sim( - name=s, - sim_dir=self.config[s]["path"], - description=self.config[s]["description"], - labels=self.config[s]["labels"], - prebuild_cmd=self.env, - build_cmd=trick_CP, - cpus=self.cpus, - size=self.config[s]["size"], - phase=self.config[s]["phase"], - log_dir=self.log_dir, - ) - all_sim_paths.append(self.config[s]["path"]) - - all_run_paths = [] # Keep a list of all paths for uniqueness check - for r in self.config[s]["runs"]: - just_RUN = r.split()[0] # Drop arguments after RUN../...py - just_RUN_dir = os.path.dirname( - just_RUN - ) # Drop path before RUN../..py - # TODO: This check will break generated runs, do we even need to check this at all? - Jordan 2022 - # if not os.path.exists(os.path.join(self.project_top_level, self.config[s]['path'], just_RUN)): - # cprint("ERROR: %s's 'run' path %s not found. Continuing but skipping this run " - # "from %s." % (s, just_RUN, self.config_file), 'DARK_RED') - # continue - if ( - just_RUN_dir in all_run_paths - and self.config[s]["parallel_safety"] == "strict" - ): - cprint( - "ERROR: %s's run directory %s is not unique in %s. With setting " - "parallel_safety: strict, you cannot have the same RUN directory listed " - "more than once per sim. Continuing but skipping this run." - % (s, r, self.config_file), - "DARK_RED", - ) - continue - - thisRun = TrickWorkflow.Run( - sim_dir=self.config[s]["path"], - input_file=r, - binary=self.config[s]["binary"], - prerun_cmd=self.env, - returns=self.config[s]["runs"][r]["returns"], - valgrind_flags=self.config[s]["runs"][r]["valgrind"], - phase=self.config[s]["runs"][r]["phase"], - log_dir=self.log_dir, - ) - - # The check for list allows all other non-list types in the yaml file, - # allowing groups to define their own comparison methodology - if isinstance(self.config[s]["runs"][r]["compare"], list): - for cmp in self.config[s]["runs"][r]["compare"]: - lhs, rhs = [s.strip() for s in cmp.split(" vs.")] - thisRun.add_comparison(test_data=lhs, baseline_data=rhs) - - if self.config[s]["runs"][r]["analyze"] is not None: - thisRun.add_analysis(cmd=self.config[s]["runs"][r]["analyze"]) - - theseRuns = [] - try: - theseRuns = ( - thisRun.multiply() - ) # If [from-to] notation used, expand runs - except RuntimeError as e: - msg = ( - "ERROR: Unable to multiply run %s in sim %s. Ignoring this run. " - "Check for bad [min-max] syntax in run keys in %s and try again.\n %s" - % (r, s, self.config_file, e) - ) - cprint(msg, "DARK_RED") - - for r in theseRuns: - thisSim.add_run(r) # Add Run/Runs to this Sim() - - all_run_paths.append( - just_RUN_dir - ) # Keep track of all runs to check parallel safety - - self.sims.append(thisSim) # Add Sim() to internal list + if not str(s).startswith('SIM'): # Ignore everything not starting with SIM + continue + if (not os.path.exists(os.path.join(self.project_top_level, self.config[s]['path'])) ): + cprint("ERROR: %s's 'path' %s not found. Continuing but skipping this entire entry from %s." + % (s, self.config[s]['path'], self.config_file), 'DARK_RED') + continue + if self.config[s]['path'] in all_sim_paths: + cprint("ERROR: %s's 'path' is not unique in %s. Continuing but ignoring this sim." + % (s, self.config_file), 'DARK_RED') + continue + # Add the CPU format string (won't fail if there is no CPU placeholder) + self.config[s]['binary'] = self.config[s]['binary'].format(cpu=self.trick_host_cpu) + # Add the full path to the build command + trick_CP=os.path.join(self.trick_dir, "bin/trick-CP") + if self.config[s]['build_args']: + trick_CP+=(' ' + self.config[s]['build_args']) + thisSim = TrickWorkflow.Sim(name=s, sim_dir=self.config[s]['path'], + description=self.config[s]['description'], labels=self.config[s]['labels'], + prebuild_cmd=self.env, build_cmd=trick_CP, + cpus=self.cpus, size=self.config[s]['size'], phase=self.config[s]['phase'], + log_dir=self.log_dir) + all_sim_paths.append(self.config[s]['path']) + + all_run_paths = [] # Keep a list of all paths for uniqueness check + for r in self.config[s]['runs']: + just_RUN = r.split()[0] # Drop arguments after RUN../...py + just_RUN_dir = os.path.dirname(just_RUN) # Drop path before RUN../..py + # TODO: This check will break generated runs, do we even need to check this at all? - Jordan 2022 + #if not os.path.exists(os.path.join(self.project_top_level, self.config[s]['path'], just_RUN)): + # cprint("ERROR: %s's 'run' path %s not found. Continuing but skipping this run " + # "from %s." % (s, just_RUN, self.config_file), 'DARK_RED') + # continue + if just_RUN_dir in all_run_paths and self.config[s]['parallel_safety'] == 'strict': + cprint("ERROR: %s's run directory %s is not unique in %s. With setting " + "parallel_safety: strict, you cannot have the same RUN directory listed " + "more than once per sim. Continuing but skipping this run." % + (s, r, self.config_file), 'DARK_RED') + continue + + thisRun = TrickWorkflow.Run(sim_dir=self.config[s]['path'], input_file=r, + binary= self.config[s]['binary'], prerun_cmd=self.env, + returns=self.config[s]['runs'][r]['returns'], + valgrind_flags=self.config[s]['runs'][r]['valgrind'], + phase=self.config[s]['runs'][r]['phase'], log_dir=self.log_dir) + + # The check for list allows all other non-list types in the yaml file, + # allowing groups to define their own comparison methodology + if isinstance(self.config[s]['runs'][r]['compare'], list): + for cmp in self.config[s]['runs'][r]['compare']: + lhs, rhs = [ s.strip() for s in cmp.split(' vs.') ] + thisRun.add_comparison(test_data=lhs, baseline_data=rhs) + + if self.config[s]['runs'][r]['analyze'] is not None: + thisRun.add_analysis(cmd=self.config[s]['runs'][r]['analyze']) + + theseRuns = [] + try: + theseRuns = thisRun.multiply() # If [from-to] notation used, expand runs + except RuntimeError as e: + msg = ("ERROR: Unable to multiply run %s in sim %s. Ignoring this run. " + "Check for bad [min-max] syntax in run keys in %s and try again.\n %s" + % (r, s, self.config_file, e) ) + cprint(msg, 'DARK_RED') + + for r in theseRuns: + thisSim.add_run(r) # Add Run/Runs to this Sim() + + all_run_paths.append(just_RUN_dir) # Keep track of all runs to check parallel safety + + self.sims.append(thisSim) # Add Sim() to internal list if len(self.sims) < 1: # At minimum, one valid SIM structure must exist - msg = ( - "ERROR: After validating config file, there is insufficient information to continue." + msg = ("ERROR: After validating config file, there is insufficient information to continue." " Check the syntax in config file %s and try again." - % (self.config_file) - ) - cprint(msg, "DARK_RED") + % (self.config_file) ) + cprint(msg, 'DARK_RED') self._cleanup() raise RuntimeError(msg) @@ -374,10 +297,10 @@ def create_test_suite(self): >>> tw.create_test_suite() """ - self.get_jobs(kind="build") - self.get_jobs(kind="run") - self.get_jobs(kind="analysis") - self.get_jobs(kind="valgrind") + self.get_jobs(kind='build') + self.get_jobs(kind='run') + self.get_jobs(kind='analysis') + self.get_jobs(kind='valgrind') def get_trick_host_cpu(self): """ @@ -392,17 +315,12 @@ def get_trick_host_cpu(self): str or None TRICK_HOST_CPU or None if it cannot be determined """ - gte_cmd = [os.path.join(self.trick_dir, "bin/trick-gte"), "TRICK_HOST_CPU"] - result = run_subprocess( - gte_cmd, m_stdout=subprocess.PIPE, m_stderr=subprocess.PIPE - ) + gte_cmd = [os.path.join(self.trick_dir, "bin/trick-gte" ), "TRICK_HOST_CPU"] + result = run_subprocess(gte_cmd, m_stdout=subprocess.PIPE, m_stderr=subprocess.PIPE) self.trick_host_cpu = result.stdout.strip() - if self.trick_host_cpu == None or self.trick_host_cpu == "": - tprint( - "ERROR: Unable to determine TRICK_HOST_CPU, you may encounter problems " - "if you continue... ", - "DARK_RED", - ) + if self.trick_host_cpu == None or self.trick_host_cpu == '': + tprint("ERROR: Unable to determine TRICK_HOST_CPU, you may encounter problems " + "if you continue... ", 'DARK_RED') self.trick_host_cpu = None return self.trick_host_cpu @@ -432,9 +350,7 @@ def get_sim(self, identifier): If identifier is not a str """ if type(identifier) != str: - raise TypeError( - "get_sim() only accepts a Sim name or Sim path from project top level" - ) + raise TypeError('get_sim() only accepts a Sim name or Sim path from project top level') for sim in self.sims: if sim.sim_dir == identifier or sim.name == identifier: return sim @@ -475,15 +391,14 @@ def get_sims(self, labels=None): elif type(labels) == list: ls = [str(l) for l in labels] else: - raise TypeError( - "get_sims() only accepts a label string or list of label strings" - ) + raise TypeError('get_sims() only accepts a label string or list of label strings') for sim in self.sims: if all(l in sim.labels for l in ls): sims_found.append(sim) return sims_found - def report(self, indent=""): + + def report(self, indent=''): """ Recursively report all internal information >>> tw = TrickWorkflow(project_top_level=this_trick, log_dir='/tmp/', trick_dir=this_trick, config_file=os.path.join(this_trick,"share/trick/trickops/tests/trick_sims.yml")) @@ -495,90 +410,41 @@ def status_summary(self): Print a summary of all jobs executed, and return 'SUCCESS' if all were successful, 'FAILURE' if any job was not successful """ - all_builds = self.get_jobs(kind="build") - all_runs = self.get_jobs(kind="run") - all_analysis = self.get_jobs(kind="analysis") + all_builds = self.get_jobs(kind='build') + all_runs = self.get_jobs(kind='run') + all_analysis = self.get_jobs(kind='analysis') all_comparisons = self.get_comparisons() - all_valgrind = self.get_jobs(kind="valgrind") - - executed_builds = [ - build - for build in all_builds - if build.get_status() != Job.Status.NOT_STARTED - ] - executed_runs = [ - run for run in all_runs if run.get_status() != Job.Status.NOT_STARTED - ] - executed_analysis = [ - a for a in all_analysis if a.get_status() != Job.Status.NOT_STARTED - ] - executed_comparisons = [ - c for c in all_comparisons if c.status != Job.Status.NOT_STARTED - ] - executed_valgrind = [ - v for v in all_valgrind if v.get_status() != Job.Status.NOT_STARTED - ] - - ok_builds = [ - build - for build in executed_builds - if build.get_status() == Job.Status.SUCCESS - ] - ok_runs = [ - run for run in executed_runs if run.get_status() == Job.Status.SUCCESS - ] - ok_analysis = [ - a for a in executed_analysis if a.get_status() == Job.Status.SUCCESS - ] - ok_comparisons = [ - c for c in executed_comparisons if c.status == Job.Status.SUCCESS - ] - ok_valgrind = [ - v for v in executed_valgrind if v.get_status() == Job.Status.SUCCESS - ] - - tprint("SUMMARY:") + all_valgrind = self.get_jobs(kind='valgrind') + + executed_builds = [ build for build in all_builds if build.get_status() != Job.Status.NOT_STARTED ] + executed_runs = [ run for run in all_runs if run.get_status() != Job.Status.NOT_STARTED ] + executed_analysis = [ a for a in all_analysis if a.get_status() != Job.Status.NOT_STARTED ] + executed_comparisons = [ c for c in all_comparisons if c.status != Job.Status.NOT_STARTED ] + executed_valgrind = [ v for v in all_valgrind if v.get_status() != Job.Status.NOT_STARTED ] + + ok_builds = [ build for build in executed_builds if build.get_status() == Job.Status.SUCCESS ] + ok_runs = [ run for run in executed_runs if run.get_status() == Job.Status.SUCCESS ] + ok_analysis = [ a for a in executed_analysis if a.get_status() == Job.Status.SUCCESS ] + ok_comparisons = [ c for c in executed_comparisons if c.status == Job.Status.SUCCESS ] + ok_valgrind = [ v for v in executed_valgrind if v.get_status() == Job.Status.SUCCESS ] + + tprint( "SUMMARY:" ) if executed_builds: - tprint( - " {0} out of {1} builds succeeded".format( - len(ok_builds), len(executed_builds) - ) - ) + tprint( " {0} out of {1} builds succeeded".format(len(ok_builds),len(executed_builds))) if executed_runs: - tprint( - " {0} out of {1} runs succeeded".format( - len(ok_runs), len(executed_runs) - ) - ) + tprint( " {0} out of {1} runs succeeded".format(len(ok_runs),len(executed_runs))) if executed_analysis: - tprint( - " {0} out of {1} analyses succeeded".format( - len(ok_analysis), len(executed_analysis) - ) - ) + tprint( " {0} out of {1} analyses succeeded".format(len(ok_analysis),len(executed_analysis))) if executed_comparisons: - tprint( - " {0} out of {1} comparisons succeeded".format( - len(ok_comparisons), len(executed_comparisons) - ) - ) + tprint( " {0} out of {1} comparisons succeeded".format(len(ok_comparisons),len(executed_comparisons))) if executed_valgrind: - tprint( - " {0} out of {1} valgrind runs succeeded".format( - len(ok_valgrind), len(executed_valgrind) - ) - ) - - if ( - executed_builds == ok_builds - and executed_runs == ok_runs - and executed_analysis == ok_analysis - and executed_comparisons == ok_comparisons - and executed_valgrind == ok_valgrind - ): - return "SUCCESS" + tprint( " {0} out of {1} valgrind runs succeeded".format(len(ok_valgrind),len(executed_valgrind))) + + if (executed_builds == ok_builds and executed_runs == ok_runs and executed_analysis == ok_analysis + and executed_comparisons == ok_comparisons and executed_valgrind == ok_valgrind) : + return 'SUCCESS' else: - return "FAILURE" + return 'FAILURE' def compare(self): """ @@ -624,27 +490,25 @@ def get_jobs(self, kind, phase=None): phases = TrickWorkflow.listify_phase(phase) jobs = [] - if kind == "build" or kind == "builds": - jobs = [sim.get_build_job() for sim in self.sims if sim.phase in phases] - elif kind == "run" or kind == "runs": - for sim in self.sims: - jobs += sim.get_run_jobs(kind="normal", phase=phases) - elif kind == "valgrind" or kind == "valgrinds": - for sim in self.sims: - jobs += sim.get_run_jobs(kind="valgrind", phase=phases) - elif kind == "analysis" or kind == "analyses" or kind == "analyze": - for sim in self.sims: - jobs += sim.get_analysis_jobs(phase=phases) + if kind == 'build' or kind == 'builds': + jobs = [ sim.get_build_job() for sim in self.sims if sim.phase in phases ] + elif kind == 'run' or kind == 'runs': + for sim in self.sims: + jobs += sim.get_run_jobs(kind='normal', phase=phases) + elif kind == 'valgrind' or kind == 'valgrinds': + for sim in self.sims: + jobs += sim.get_run_jobs(kind='valgrind', phase=phases) + elif kind == 'analysis' or kind == 'analyses' or kind == 'analyze': + for sim in self.sims: + jobs += sim.get_analysis_jobs(phase=phases) else: - raise TypeError( - "get_jobs() only accepts kinds: build, run, valgrind, analysis" - ) + raise TypeError('get_jobs() only accepts kinds: build, run, valgrind, analysis') # If these jobs are of type SingleRun and self.quiet is True, tell the jobs to # skip the variable server connection logic for job in jobs: if self.quiet and isinstance(job, SingleRun): job.set_use_var_server(False) - return jobs + return (jobs) def get_comparisons(self): """ @@ -660,7 +524,7 @@ def get_comparisons(self): list List of Comparison objects """ - return [c for sim in self.sims for run in sim.runs for c in run.comparisons] + return ([ c for sim in self.sims for run in sim.runs for c in run.comparisons ]) def get_unique_comparison_dirs(self): """ @@ -683,11 +547,11 @@ def get_unique_comparison_dirs(self): """ all_cmp_dirnames = [] # list of tuples ( test_dir, baseline_dir ) for sim in self.sims: - for run in sim.runs: - for cmp in run.comparisons: - all_cmp_dirnames.append(cmp.get_dirnames()) + for run in sim.runs: + for cmp in run.comparisons: + all_cmp_dirnames.append(cmp.get_dirnames()) # Reduce full list to unique list - return list(set(all_cmp_dirnames)) + return(list(set(all_cmp_dirnames))) def get_koviz_report_job(self, test_dir, baseline_dir, pres=None): """ @@ -716,44 +580,28 @@ def get_koviz_report_job(self, test_dir, baseline_dir, pres=None): (Job() instance for the run directories given or None if error encountered, error details or None if successful) """ - if os.system(self.env + " which koviz > /dev/null 2>&1") != 0: + if os.system(self.env + ' which koviz > /dev/null 2>&1') != 0: msg = "ERROR: koviz is not found in PATH. Returning None in get_koviz_report_job()" - tprint(msg, "DARK_RED") + tprint (msg, 'DARK_RED') return None, msg dirs = [test_dir, baseline_dir] for dir in dirs: - if not os.path.exists(dir): - msg = ( - "ERROR: %s not found, Returning None in get_koviz_report_job()" - % (dir) - ) - tprint(msg, "DARK_RED") - return None, msg - cmd = self.env + " koviz -platform offscreen -a" + if not os.path.exists(dir): + msg = "ERROR: %s not found, Returning None in get_koviz_report_job()" % (dir) + tprint(msg, 'DARK_RED') + return None, msg + cmd = (self.env + " koviz -platform offscreen -a") if pres: - cmd += " -pres %s " % pres - cmd += " -pdf %s %s %s" % ( - os.path.join( - self.log_dir, - (unixify_string(test_dir) + "_vs_" + unixify_string(baseline_dir)) - + ".pdf", - ), - test_dir, - baseline_dir, - ) - name = "koviz report %s vs. %s" % (test_dir, baseline_dir) - return ( - Job( - name=name, - command=cmd, - log_file=os.path.join(self.log_dir, "." + unixify_string(name)), - expected_exit_status=0, - ), - None, - ) + cmd+= (" -pres %s " % pres ) + cmd+= (" -pdf %s %s %s" % (os.path.join(self.log_dir, + (unixify_string(test_dir)+'_vs_' + unixify_string(baseline_dir)) + '.pdf'), + test_dir, baseline_dir) ) + name='koviz report %s vs. %s' % (test_dir, baseline_dir) + return(Job(name=name, command=cmd, log_file=os.path.join(self.log_dir,"."+unixify_string(name)), + expected_exit_status=0), None) def get_koviz_report_jobs(self): - """ + ''' Loop over all runs for all sims and generate a koviz pdf report job for each unique run directory comparison found. @@ -770,22 +618,18 @@ def get_koviz_report_jobs(self): ------- Tuple List of 'koviz' commands executed, List of errors - """ + ''' koviz_jobs = [] koviz_errors = [] - all_cmp_dirnames = ( - self.get_unique_comparison_dirs() - ) # List of (test_dir, baseline_dir) tuples + all_cmp_dirnames = self.get_unique_comparison_dirs() # List of (test_dir, baseline_dir) tuples # Generate koviz reports for the given test_dir, baseline_dir pairs - for test_dir, baseline_dir in all_cmp_dirnames: - if test_dir and baseline_dir: # Will be None if dir is empty - job, error = self.get_koviz_report_job( - test_dir, baseline_dir, pres="error" - ) - if job: - koviz_jobs.append(job) - if error: - koviz_errors.append(error) + for (test_dir, baseline_dir) in all_cmp_dirnames: + if test_dir and baseline_dir: # Will be None if dir is empty + job, error = self.get_koviz_report_job(test_dir, baseline_dir, pres='error') + if job: + koviz_jobs.append(job) + if error: + koviz_errors.append(error) return koviz_jobs, koviz_errors class Sim(object): @@ -794,20 +638,8 @@ class Sim(object): key in the dict read will become a single instance of this management class stored in the TrickWorkflow.sims list. """ - - def __init__( - self, - name, - sim_dir, - description=None, - labels=[], - prebuild_cmd="", - build_cmd="trick-CP", - cpus=3, - size=2200000, - phase=0, - log_dir="/tmp", - ): + def __init__(self, name, sim_dir, description=None, labels=[], prebuild_cmd='', + build_cmd='trick-CP', cpus=3, size=2200000, phase=0, log_dir='/tmp'): """ Initialize this instance. @@ -835,24 +667,22 @@ def __init__( log_dir: str Directory in which log files will be written """ - self.name = name # Name of sim - self.sim_dir = sim_dir # Path to sim directory wrt to top level of project - self.description = description # Description of sim - self.labels = ( - labels # Options list of user-specified labels associated w/ this sim - ) - self.prebuild_cmd = prebuild_cmd # Optional string to execute in shell immediately before building - self.build_cmd = build_cmd # Build command for sim - self.cpus = cpus # Number of CPUs to use in build - self.size = size # Estimated size of successful build output in bytes - self.phase = phase # Phase associated with this sim build - self.log_dir = log_dir # Directory for which log file should be written - self.build_job = None # Contains Build Job instance - self.runs = [] # List of normal Run instances - self.valgrind_runs = [] # List of valgrind Run instances - self.printer = ColorStr() # Color printer utility - - def get_build_job(self): + self.name = name # Name of sim + self.sim_dir = sim_dir # Path to sim directory wrt to top level of project + self.description = description # Description of sim + self.labels = labels # Options list of user-specified labels associated w/ this sim + self.prebuild_cmd = prebuild_cmd # Optional string to execute in shell immediately before building + self.build_cmd = build_cmd # Build command for sim + self.cpus = cpus # Number of CPUs to use in build + self.size = size # Estimated size of successful build output in bytes + self.phase = phase # Phase associated with this sim build + self.log_dir = log_dir # Directory for which log file should be written + self.build_job = None # Contains Build Job instance + self.runs = [] # List of normal Run instances + self.valgrind_runs = [] # List of valgrind Run instances + self.printer = ColorStr() # Color printer utility + + def get_build_job( self): """ Create the FileSizeJob(Job) instance if not already created and return it for this Sim @@ -867,21 +697,15 @@ def get_build_job(self): """ if not self.build_job: - name = "Build " + self.sim_dir - self.build_job = FileSizeJob( - name=name, - command=( - "%s cd %s && export MAKEFLAGS=-j%d && %s" - % (self.prebuild_cmd, self.sim_dir, self.cpus, self.build_cmd) - ), - log_file=os.path.join( - self.log_dir, unixify_string(self.sim_dir) + "_build.txt" - ), - size=self.size, - ) - return self.build_job - - def get_run_jobs(self, kind="normal", phase=None): + name = 'Build ' + self.sim_dir + self.build_job = FileSizeJob(name=name, + command=("%s cd %s && export MAKEFLAGS=-j%d && %s" % + (self.prebuild_cmd, self.sim_dir, self.cpus, self.build_cmd)), + log_file=os.path.join(self.log_dir, unixify_string(self.sim_dir)+'_build.txt'), + size=self.size ) + return (self.build_job) + + def get_run_jobs( self, kind='normal', phase=None): """ Collect all SingleRun() instances and return them for all sims subject to the filtering paramters kind and phase @@ -906,15 +730,13 @@ def get_run_jobs(self, kind="normal", phase=None): # Transform given phase into a list phases = TrickWorkflow.listify_phase(phase) all_jobs = [] - if kind == "valgrind": - all_jobs = [ - r.get_run_job() for r in self.valgrind_runs if r.phase in phases - ] + if (kind == 'valgrind'): + all_jobs = [r.get_run_job() for r in self.valgrind_runs if r.phase in phases] else: all_jobs = [r.get_run_job() for r in self.runs if r.phase in phases] - return all_jobs + return (all_jobs) - def get_analysis_jobs(self, phase=None): + def get_analysis_jobs( self, phase=None): """ Collect all Job() instances for all analysis across all sim runs and valgrind runs @@ -935,11 +757,7 @@ def get_analysis_jobs(self, phase=None): """ # Transform given phase into a list phases = TrickWorkflow.listify_phase(phase) - return [ - r.analysis - for r in (self.runs + self.valgrind_runs) - if (r.analysis and r.phase in phases) - ] + return ([r.analysis for r in (self.runs + self.valgrind_runs) if (r.analysis and r.phase in phases) ]) def get_run(self, input_file): """ @@ -966,13 +784,11 @@ def get_run(self, input_file): If input is not a str """ if type(input_file) != str: - raise TypeError( - "get_run() only accepts the unique key representing the entire input to" - ' the sim binary. Ex: "RUN_test/input.py --flags-too"' - ) + raise TypeError('get_run() only accepts the unique key representing the entire input to' + ' the sim binary. Ex: "RUN_test/input.py --flags-too"') for run in self.runs: if run.input_file == input_file: - return run + return run return None def get_runs(self): @@ -1008,7 +824,7 @@ def get_phase(self): """ return self.phase - def set_phase(self, phase): + def set_phase( self, phase): """ Set the phase member variable. Phase is an integer in the range(TrickWorkflow.allowed_phase_range['min'], TrickWorkflow.allowed_phase_range['max']) which can be used to order sim builds when a workflow cannot @@ -1026,24 +842,15 @@ def set_phase(self, phase): phase : int phase to change to """ - if ( - not isinstance(phase, int) - or phase < TrickWorkflow.allowed_phase_range["min"] - or phase > TrickWorkflow.allowed_phase_range["max"] - ): - msg = ( - "ERROR: set_phase() for SIM %s must be an integer between [%s, %s]" - % ( - self.name, - TrickWorkflow.allowed_phase_range["min"], - TrickWorkflow.allowed_phase_range["max"], - ) - ) + if (not isinstance(phase, int) or phase < TrickWorkflow.allowed_phase_range['min'] or + phase > TrickWorkflow.allowed_phase_range['max']): + msg =("ERROR: set_phase() for SIM %s must be an integer between [%s, %s]" + % (self.name, TrickWorkflow.allowed_phase_range['min'], TrickWorkflow.allowed_phase_range['max'])) raise RuntimeError(msg) else: self.phase = phase - def add_run(self, run): + def add_run( self, run): """ Append a new Run() instance to the internal run lists. Appends to valgrind list if run.valgrind_flags is not None, appends to normal run list otherwise @@ -1057,12 +864,12 @@ def add_run(self, run): run : Run() Instance to add """ - if run.valgrind_flags: + if (run.valgrind_flags): self.valgrind_runs.append(run) else: self.runs.append(run) - def pop_run(self, input_file): + def pop_run( self, input_file): """ Remove a run by its unique self.input_file value @@ -1082,10 +889,10 @@ def pop_run(self, input_file): Instance in this sim's runs list matching self.input_file """ for i, run in enumerate(self.runs): - if run.input_file == input_file: - return self.runs.pop(i) + if run.input_file == input_file: + return self.runs.pop(i) - def compare(self): + def compare( self): """ Run compare() on all runs for this sim @@ -1100,7 +907,7 @@ def compare(self): """ return any([r.compare() for r in self.runs]) - def report(self, indent=""): + def report(self, indent=''): """ Report this sims information verbosely, ignoring members that are None @@ -1111,49 +918,31 @@ def report(self, indent=""): """ if self.name: - tprint(indent + "Name: " + self.name) + tprint(indent + "Name: " + self.name) else: - tprint(indent + self.sim_dir) + tprint(indent + self.sim_dir) if self.description: - tprint(indent + "Description: " + str(self.description)) + tprint(indent + "Description: " + str(self.description)) if self.labels: - tprint(indent + "Labels: " + str(", ".join(self.labels))) - tprint( - indent - + " Build: %-20s %-60s " - % ( - self.build_job._translate_status() - if self.build_job - else printer.colorstr("NOT RUN", "DARK_YELLOW"), - self.sim_dir, - ) - ) + tprint(indent + "Labels: " + str(', '.join(self.labels))) + tprint(indent + " Build: %-20s %-60s " %(self.build_job._translate_status() + if self.build_job else printer.colorstr('NOT RUN', 'DARK_YELLOW'), self.sim_dir)) if self.runs: - tprint(indent + " Runs:") - for run in self.runs: - run.report(indent=indent + " ") + tprint(indent + " Runs:") + for run in self.runs: + run.report(indent=indent+' ') if self.valgrind_runs: - tprint(indent + " Valgrind Runs:") - for run in self.valgrind_runs: - run.report(indent=indent + " ") + tprint(indent + " Valgrind Runs:") + for run in self.valgrind_runs: + run.report(indent=indent+' ') class Run(object): """ Management class for run content read from yml config file. Each key in the runs: sub-dict will become a single instance of this management class """ - - def __init__( - self, - sim_dir, - input_file, - binary, - prerun_cmd="", - returns=0, - valgrind_flags=None, - phase=0, - log_dir="/tmp/", - ): + def __init__(self, sim_dir, input_file, binary, prerun_cmd = '', returns=0, valgrind_flags=None, + phase=0, log_dir='/tmp/'): """ Initialize this instance. @@ -1181,23 +970,23 @@ def __init__( log_dir : str Directory in which log files will be written """ - self.sim_dir = sim_dir # Path to sim directory wrt to top level of project for this run + self.sim_dir = sim_dir # Path to sim directory wrt to top level of project for this run self.prerun_cmd = prerun_cmd # Optional string to execute in shell immediately before running (env) self.input_file = input_file # Full RUN.../input.py --any-flags --as-well, relative to sim_dir - self.returns = returns # Expected exit code on success for this run + self.returns = returns # Expected exit code on success for this run self.valgrind_flags = valgrind_flags # If not None, this run is to be run in valgrind w/ these flags - self.phase = phase # Phase associated with this run - self.log_dir = log_dir # Dir where all logged output will go - self.just_input = self.input_file.split(" ")[0] # Strip flags if any + self.phase = phase # Phase associated with this run + self.log_dir = log_dir # Dir where all logged output will go + self.just_input = self.input_file.split(' ')[0] # Strip flags if any # Derive Just the "RUN_something" part of run_dir_path self.just_run_dir = os.path.dirname(self.just_input) # Derive Path to run directory wrt to top level of project self.run_dir_path = os.path.join(self.sim_dir, self.just_run_dir) # Populated later - self.binary = binary # Name of binary - self.run_job = None # SingleRun Job instance for this run - self.comparisons = [] # List of comparison objects associated with this run - self.analysis = None # Job instance of after-run-completes custom analysis + self.binary = binary # Name of binary + self.run_job = None # SingleRun Job instance for this run + self.comparisons = [] # List of comparison objects associated with this run + self.analysis = None # Job instance of after-run-completes custom analysis def add_comparison(self, test_data, baseline_data): """ @@ -1213,8 +1002,8 @@ def add_comparison(self, test_data, baseline_data): baseline_dir : str path to file containing baseline logged data """ - comparison = TrickWorkflow.Comparison(test_data, baseline_data) - self.comparisons.append(comparison) + comparison = TrickWorkflow.Comparison( test_data, baseline_data ); + self.comparisons.append( comparison ) def add_analysis(self, cmd): """ @@ -1229,23 +1018,12 @@ def add_analysis(self, cmd): literal string representing command to execute post-run """ if self.analysis: - tprint( - "WARNING: Overwriting analysis definition for %s's %s" - % (self.sim_dir, self.input_file), - "DARK_YELLOW", - ) - logfile = ( - os.path.join(self.log_dir, unixify_string(self.sim_dir)) - + "_" - + unixify_string(self.input_file) - + "_analysis.txt" - ) - self.analysis = Job( - name=textwrap.shorten(cmd, width=90), - command=self.prerun_cmd + " " + cmd, - log_file=logfile, - expected_exit_status=0, - ) + tprint("WARNING: Overwriting analysis definition for %s's %s" % (self.sim_dir, + self.input_file), 'DARK_YELLOW') + logfile = (os.path.join(self.log_dir, unixify_string(self.sim_dir)) + +'_'+ unixify_string(self.input_file) + '_analysis.txt') + self.analysis = Job(name=textwrap.shorten(cmd, width=90), command=self.prerun_cmd + " " +cmd, + log_file=logfile, expected_exit_status=0) def get_phase(self): """ @@ -1258,7 +1036,7 @@ def get_phase(self): """ return self.phase - def set_phase(self, phase): + def set_phase( self, phase): """ Set the phase member variable. Phase is an integer in the range(TrickWorkflow.allowed_phase_range['min'], TrickWorkflow.allowed_phase_range['max']) which can be used to order sim runs when a workflow cannot @@ -1279,25 +1057,16 @@ def set_phase(self, phase): # TODO: This is very similar to Sim.set_phase() in functionality but I didn't want to create # a base class just to support this single instance of reducing code duplication # -Jordan 12/2022 - if ( - not isinstance(phase, int) - or phase < TrickWorkflow.allowed_phase_range["min"] - or phase > TrickWorkflow.allowed_phase_range["max"] - ): - msg = ( - "ERROR: set_phase() for %s/%s must be an integer between [%s, %s]" - % ( - self.sim_dir, - self.input_file, - TrickWorkflow.allowed_phase_range["min"], - TrickWorkflow.allowed_phase_range["max"], - ) - ) + if (not isinstance(phase, int) or phase < TrickWorkflow.allowed_phase_range['min'] or + phase > TrickWorkflow.allowed_phase_range['max']): + msg =("ERROR: set_phase() for %s/%s must be an integer between [%s, %s]" + % (self.sim_dir, self.input_file, TrickWorkflow.allowed_phase_range['min'], + TrickWorkflow.allowed_phase_range['max'])) raise RuntimeError(msg) else: self.phase = phase - def compare(self): + def compare( self): """ Execute all internal comparisons for this run @@ -1312,7 +1081,7 @@ def compare(self): """ return any([c.compare() != Job.Status.SUCCESS for c in self.comparisons]) - def report(self, indent=""): + def report(self, indent=''): """ Report this run's information verbosely, ignoring members that are None @@ -1322,23 +1091,16 @@ def report(self, indent=""): prepend the report with this custom string """ - tprint( - indent - + " %-20s %s" - % ( - self.run_job._translate_status() - if self.run_job - else printer.colorstr("NOT RUN", "DARK_YELLOW"), - self.input_file, - ) - ) + tprint(indent + " %-20s %s" % (self.run_job._translate_status() + if self.run_job else printer.colorstr('NOT RUN', 'DARK_YELLOW'), + self.input_file)) if self.comparisons: - tprint(indent + " Run Comparisons:") - for comparison in self.comparisons: - comparison.report(indent=indent + " ") + tprint(indent + " Run Comparisons:") + for comparison in self.comparisons: + comparison.report(indent=indent+' ') if self.analysis: - tprint(indent + " Run Analysis:") - tprint(indent + " " + self.analysis.report()) + tprint(indent + " Run Analysis:") + tprint(indent + " " + self.analysis.report()) def get_run_job(self): """ @@ -1353,35 +1115,25 @@ def get_run_job(self): SingleRun() Job instance for this run """ if not self.run_job: - name = "Run " + name = 'Run ' cmd = "%s cd %s && " % (self.prerun_cmd, self.sim_dir) sim_name = os.path.basename(os.path.normpath(self.sim_dir)) logfile = os.path.join(self.log_dir, unixify_string(self.sim_dir)) if self.valgrind_flags: - cmd += "valgrind %s --log-file=%s " % ( - self.valgrind_flags, - ( - os.path.join(self.log_dir, sim_name) - + "_valgrind_" - + unixify_string(self.input_file) - + ".valgrind" - ), - ) - logfile += "_valgrind" - name += "Valgrind " - logfile += "_" + unixify_string(self.input_file) + ".txt" - cmd += " ./%s %s" % (self.binary, self.input_file) - name += self.sim_dir + " " + self.input_file - - self.run_job = SingleRun( - name=name, - command=(cmd), - expected_exit_status=self.returns, - log_file=logfile, - ) - return self.run_job + cmd += ( "valgrind %s --log-file=%s " % (self.valgrind_flags, + (os.path.join(self.log_dir, sim_name) +'_valgrind_' + + unixify_string(self.input_file) + '.valgrind') )) + logfile += '_valgrind' + name += 'Valgrind ' + logfile += "_" + unixify_string(self.input_file) + '.txt' + cmd += (" ./%s %s" % (self.binary, self.input_file)) + name += self.sim_dir + ' ' + self.input_file + + self.run_job = SingleRun(name=name, command=(cmd), + expected_exit_status=self.returns, log_file=logfile) + return (self.run_job) def _get_range_list(self, pattern): """ @@ -1407,41 +1159,33 @@ def _get_range_list(self, pattern): RuntimeError If pattern is unrecognized or contains errors """ - must_exist = ["[", "]", "-"] + must_exist = ['[', ']', '-'] if any([char not in pattern for char in must_exist]): - msg = ( - 'ERROR: Pattern %s doesn\'t match expected syntax of "[min-max]"' - % (pattern) - ) - raise RuntimeError(msg) - min, max = pattern.strip("[").strip("]").split("-") + msg = ("ERROR: Pattern %s doesn't match expected syntax of \"[min-max]\"" % (pattern)) + raise RuntimeError(msg) + min, max = pattern.strip('[').strip(']').split('-') if len(min) != len(max): - msg = "ERROR: Pattern %s has inconsistent leading zeros." % (pattern) - raise RuntimeError(msg) + msg = ("ERROR: Pattern %s has inconsistent leading zeros." % (pattern)) + raise RuntimeError(msg) leading_zeros = int(len(min)) try: - min = int(min) + min = int(min) except ValueError as e: - msg = ( - "ERROR: Pattern %s minimum cannot be converted to integer. \n%s" - % (pattern, e) - ) - raise RuntimeError(msg) + msg = ("ERROR: Pattern %s minimum cannot be converted to integer. \n%s" % (pattern, e)) + raise RuntimeError(msg) try: - max = int(max) + max = int(max) except ValueError as e: - msg = ( - "ERROR: Pattern %s maximum cannot be converted to integer. \n%s" - % (pattern, e) - ) - raise RuntimeError(msg) + msg = ("ERROR: Pattern %s maximum cannot be converted to integer. \n%s" % (pattern, e)) + raise RuntimeError(msg) if min >= (max): - msg = "ERROR: Pattern %s minimum must be less than maximum." % pattern - raise RuntimeError(msg) + msg = ("ERROR: Pattern %s minimum must be less than maximum." % pattern) + raise RuntimeError(msg) range_list = [] - for num in range(min, max + 1): - range_list.append(str(num).zfill(leading_zeros)) - return list(range_list) + for num in range(min, max+1): + range_list.append(str(num).zfill(leading_zeros)) + return (list(range_list)) + def multiply(self): """ @@ -1481,19 +1225,19 @@ def multiply(self): """ rs = TrickWorkflow._find_range_string(self.input_file) if rs is None: - return [self] + return [self] else: - range_list = self._get_range_list(rs) - multiplied_runs = [] - for i in range_list: - # replace the range string notation with the single run equivalent - acopy = copy.deepcopy(self) - acopy.input_file = self.input_file.replace(rs, i) - # Add comparisons back as multiplied set - for c in acopy.comparisons: - c.pattern_replace(expecting_pattern=rs, replace_with=i) - multiplied_runs.append(acopy) - return multiplied_runs + range_list = self._get_range_list(rs) + multiplied_runs = [] + for i in range_list: + # replace the range string notation with the single run equivalent + acopy = copy.deepcopy(self) + acopy.input_file = self.input_file.replace(rs, i) + # Add comparisons back as multiplied set + for c in acopy.comparisons: + c.pattern_replace(expecting_pattern=rs, replace_with=i) + multiplied_runs.append(acopy) + return multiplied_runs class Comparison(object): """ @@ -1502,7 +1246,6 @@ class Comparison(object): test_data: path to file that represents test data (data generated by a run) baseline_data: path to file that represents baseline data for a run """ - def __init__(self, test_data, baseline_data): """ Initialize this instance. Environment variables used within the test data and baseline data paths will be expanded. @@ -1517,15 +1260,11 @@ def __init__(self, test_data, baseline_data): baseline_data : str Path to a single baseline logged data file """ - self.test_data = os.path.expandvars( - test_data - ) # Test data file with respect to project top level - self.baseline_data = os.path.expandvars( - baseline_data - ) # Baseline data file with respect to project top level - self.status = Job.Status.NOT_STARTED # Status of comparison - self.error = None # Error details if found - self.missing = [] # List of Strings with details of missing files if any + self.test_data = os.path.expandvars(test_data) # Test data file with respect to project top level + self.baseline_data = os.path.expandvars(baseline_data) # Baseline data file with respect to project top level + self.status = Job.Status.NOT_STARTED # Status of comparison + self.error = None # Error details if found + self.missing = [] # List of Strings with details of missing files if any def compare(self): """ @@ -1541,20 +1280,20 @@ def compare(self): status of the comparison: Job.Status.SUCCESS on success, Job.Status.FAILED """ for hs in [self.test_data, self.baseline_data]: - if not os.path.exists(hs): - self.missing.append(hs) - self.status = Job.Status.FAILED + if not os.path.exists(hs) : + self.missing.append(hs) + self.status = Job.Status.FAILED if self.missing: - return self.status - td = hashlib.new("md5", usedforsecurity=False) - bd = hashlib.new("md5", usedforsecurity=False) - td.update(open(self.test_data, "rb").read()) - bd.update(open(self.baseline_data, "rb").read()) - if td.hexdigest() != bd.hexdigest(): + return self.status + td = hashlib.new('md5', usedforsecurity=False) + bd = hashlib.new('md5', usedforsecurity=False) + td.update(open(self.test_data,'rb').read()) + bd.update(open(self.baseline_data,'rb').read()) + if (td.hexdigest() != bd.hexdigest()): self.status = Job.Status.FAILED else: self.status = Job.Status.SUCCESS - return self.status + return self.status def get_status(self): """ @@ -1577,10 +1316,9 @@ def _translate_status(self): Utility function that takes in a status and colors it, for easier reporting """ text, color = { - Job.Status.NOT_STARTED: ("NOT RUN", "DARK_YELLOW"), - Job.Status.SUCCESS: ("OK", "DARK_GREEN"), - Job.Status.FAILED: ("FAIL", "DARK_RED"), - }[self.get_status()] + Job.Status.NOT_STARTED: ('NOT RUN', 'DARK_YELLOW'), + Job.Status.SUCCESS: ('OK', 'DARK_GREEN'), + Job.Status.FAILED: ('FAIL', 'DARK_RED') }[self.get_status()] return printer.colorstr(text, color) def get_dirnames(self): @@ -1602,12 +1340,12 @@ def get_dirnames(self): test_dirname = os.path.dirname(self.test_data) baseline_dirname = os.path.dirname(self.baseline_data) if not os.path.exists(test_dirname): - test_dirname = None + test_dirname = None if not os.path.exists(baseline_dirname): - baseline_dirname = None + baseline_dirname = None return (test_dirname, baseline_dirname) - def report(self, indent=""): + def report (self, indent=''): """ Report this comparison's information verbosely @@ -1617,12 +1355,12 @@ def report(self, indent=""): prepend the report with this custom string """ - string = indent + "%-22s %s" % (self._translate_status(), self.test_data) + string = indent + "%-22s %s" % (self._translate_status(), self.test_data) if self.test_data in self.missing: - string += printer.colorstr(" (missing)", "DARK_RED") - string += " vs. %s" % (self.baseline_data) + string += printer.colorstr(" (missing)", 'DARK_RED') + string += " vs. %s" % (self.baseline_data) if self.baseline_data in self.missing: - string += printer.colorstr(" (missing)", "DARK_RED") + string += printer.colorstr(" (missing)", 'DARK_RED') tprint(string) def pattern_replace(self, expecting_pattern, replace_with): @@ -1645,21 +1383,17 @@ def pattern_replace(self, expecting_pattern, replace_with): """ rsb = TrickWorkflow._find_range_string(self.baseline_data) rst = TrickWorkflow._find_range_string(self.test_data) - if rsb is None and rst is None: # If no patterns, do nothing - return + if rsb is None and rst is None: # If no patterns, do nothing + return if (rsb and rsb != expecting_pattern) or (rst and rst != expecting_pattern): - msg = ( - "ERROR: [min-max] pattern from run (%s) must match pattern in run's" - " comparisons test (%s) and baseline (%s) sections, if specified." - % (expecting_pattern, rst, rsb) - ) - raise RuntimeError(msg) + msg = ("ERROR: [min-max] pattern from run (%s) must match pattern in run's" + " comparisons test (%s) and baseline (%s) sections, if specified." + % (expecting_pattern, rst, rsb)) + raise RuntimeError(msg) if rsb: - self.baseline_data = self.baseline_data.replace( - expecting_pattern, replace_with - ) + self.baseline_data = self.baseline_data.replace(expecting_pattern, replace_with) if rst: - self.test_data = self.test_data.replace(expecting_pattern, replace_with) + self.test_data = self.test_data.replace(expecting_pattern, replace_with) class SingleRun(Job): @@ -1667,10 +1401,7 @@ class SingleRun(Job): A single trick simulation run Job. SingleRun's can optionally connect to the trick variable server to get progress bar information. """ - - def __init__( - self, name, command, log_file, expected_exit_status=0, use_var_server=True - ): + def __init__(self, name, command, log_file, expected_exit_status=0, use_var_server=True): """ Initialize this instance. @@ -1685,22 +1416,18 @@ def __init__( """ self._use_var_server = use_var_server self._connected = False - super().__init__( - name=name, - command=command, - log_file=log_file, - expected_exit_status=expected_exit_status, - ) + super().__init__(name=name, command=command, log_file=log_file, + expected_exit_status=expected_exit_status) def set_use_var_server(self, value): - if not isinstance(value, bool): - msg = "ERROR: SingleRun.set_use_var_server() Requires a True/False value" + if (not isinstance(value, bool)): + msg =("ERROR: SingleRun.set_use_var_server() Requires a True/False value") raise RuntimeError(msg) else: self._use_var_server = value def get_use_var_server(self): - return self._use_var_server + return (self._use_var_server) def start(self): """ @@ -1717,7 +1444,6 @@ def start(self): # has finished. def connect(): import psutil - while self.get_status() is self.Status.RUNNING: # The base-class start() call will have already populated self._process.pid, # but that pid may be incompatible with the upcoming find_simulation call @@ -1729,26 +1455,24 @@ def connect(): # self._process.pid if not found sim_pid = self._process.pid try: - children = psutil.Process(self._process.pid).children( - recursive=True - ) + children = psutil.Process(self._process.pid).children(recursive=True) outerbreak = False for child in children: for i in child.cmdline(): - if re.search(".*S_main", i): + if re.search('.*S_main', i): sim_pid = child.pid outerbreak = True break if outerbreak: break - except Exception: + except Exception as e: sim_pid = self._process.pid # Now connect to the sim_pid try: self._variable_server = variable_server.find_simulation( - pid=sim_pid, timeout=5 - ) - self._variable_server.add_variables(*self._create_variables()) + pid=sim_pid, timeout=5) + self._variable_server.add_variables( + *self._create_variables()) self._variable_server.set_period(0.1) self._connected = True return @@ -1757,11 +1481,11 @@ def connect(): # If a SingleRun job terminates before the thread can connect to the # variable server, Trick's variable_server module throws an IOError # with the message: The remote endpoint has closed the connection - except IOError: + except IOError as e: pass if self._use_var_server: - thread = threading.Thread(target=connect, name="Looking for " + self.name) + thread = threading.Thread(target=connect, name='Looking for ' + self.name) thread.daemon = True thread.start() @@ -1769,29 +1493,29 @@ def get_status_string_line_count(self): return super(SingleRun, self).get_status_string_line_count() + 1 def _not_started_string(self): - return super(SingleRun, self)._not_started_string() + "\n" + return super(SingleRun, self)._not_started_string() + '\n' def _running_string(self): elapsed_time = super(SingleRun, self)._running_string() if self._connected: - return ( - elapsed_time + self._connected_string() + "\n" + self._connected_bar() - ) + return (elapsed_time + self._connected_string() + '\n' + + self._connected_bar()) - return elapsed_time + "\n" + create_progress_bar(0, "Connecting") + return (elapsed_time + '\n' + + create_progress_bar(0, 'Connecting')) def _success_string(self): text = super(SingleRun, self)._success_string() if self._connected: text += self._connected_string() - return text + "\n" + self._success_progress_bar + return text + '\n' + self._success_progress_bar def _failed_string(self): text = super(SingleRun, self)._failed_string() if self._connected: text += self._connected_string() - return text + "\n" + self._failed_progress_bar + return text + '\n' + self._failed_progress_bar def die(self): try: @@ -1807,24 +1531,25 @@ def __del__(self): pass def _create_variables(self): - self._tics = variable_server.Variable("trick_sys.sched.time_tics", type_=float) + self._tics = variable_server.Variable( + 'trick_sys.sched.time_tics', type_=float) self._tics_per_sec = variable_server.Variable( - "trick_sys.sched.time_tic_value", type_=float - ) + 'trick_sys.sched.time_tic_value', type_=float) self._terminate_time = variable_server.Variable( - "trick_sys.sched.terminate_time", type_=float - ) + 'trick_sys.sched.terminate_time', type_=float) return self._tics, self._tics_per_sec, self._terminate_time def _connected_string(self): - return " {0} {1}".format(self._sim_time(), self._average_speed()) + return ' {0} {1}'.format( + self._sim_time(), self._average_speed()) def _connected_bar(self): if self._terminate_time.value <= 0.0: - progress = 0.0 + progress = 0.0 else: - progress = self._tics.value / self._terminate_time.value - return create_progress_bar(progress, "{0:.1f}%".format(100 * progress)) + progress = self._tics.value / self._terminate_time.value + return create_progress_bar( + progress, '{0:.1f}%'.format(100 * progress)) def _sim_time(self): """ @@ -1835,9 +1560,8 @@ def _sim_time(self): str A string for displaying sim time. """ - return "Sim Time: {0:7.1f} sec".format( - self._tics.value / self._tics_per_sec.value - ) + return 'Sim Time: {0:7.1f} sec'.format( + self._tics.value / self._tics_per_sec.value) def _average_speed(self): """ @@ -1849,8 +1573,8 @@ def _average_speed(self): A string for displaying the ratio of sim time to real time. """ elapsed_time = ( - self._stop_time if self._stop_time else time.time() - ) - self._start_time - return "Average Speed: {0:4.1f} X".format( - self._tics.value / self._tics_per_sec.value / elapsed_time - ) + (self._stop_time if self._stop_time else time.time()) + - self._start_time) + return 'Average Speed: {0:4.1f} X'.format( + self._tics.value / self._tics_per_sec.value / elapsed_time) + diff --git a/test/.gitignore b/test/.gitignore index ca7772f8d..f3d79c4a5 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -27,5 +27,3 @@ build S_sie.json *.ckpnt MonteCarlo_Meta_data_output -*.xml -SIM_mtv/models/test_client/test_client diff --git a/test/SIM_exclusion_mechanisms/models/trickified/.gitignore b/test/SIM_exclusion_mechanisms/models/trickified/.gitignore index 53064b3fe..23cce3683 100644 --- a/test/SIM_exclusion_mechanisms/models/trickified/.gitignore +++ b/test/SIM_exclusion_mechanisms/models/trickified/.gitignore @@ -1,3 +1,2 @@ python -trickified.o full_file diff --git a/test/SIM_trickified/trickified_project/trickified/.gitignore b/test/SIM_trickified/trickified_project/trickified/.gitignore index 7f5440dcd..b4748bbf3 100644 --- a/test/SIM_trickified/trickified_project/trickified/.gitignore +++ b/test/SIM_trickified/trickified_project/trickified/.gitignore @@ -2,4 +2,3 @@ build python trick full_file -*.o diff --git a/test/SIM_trickified_archive/trickified_project/trickified/.gitignore b/test/SIM_trickified_archive/trickified_project/trickified/.gitignore index 1d77349de..987ae75c5 100644 --- a/test/SIM_trickified_archive/trickified_project/trickified/.gitignore +++ b/test/SIM_trickified_archive/trickified_project/trickified/.gitignore @@ -1,5 +1,4 @@ build python trick -*.o S_overrides_trickify.mk diff --git a/test/SIM_trickified_object/trickified_project/trickified/.gitignore b/test/SIM_trickified_object/trickified_project/trickified/.gitignore index 1d77349de..987ae75c5 100644 --- a/test/SIM_trickified_object/trickified_project/trickified/.gitignore +++ b/test/SIM_trickified_object/trickified_project/trickified/.gitignore @@ -1,5 +1,4 @@ build python trick -*.o S_overrides_trickify.mk diff --git a/test/SIM_trickified_shared/trickified_project/trickified/.gitignore b/test/SIM_trickified_shared/trickified_project/trickified/.gitignore index 1d77349de..987ae75c5 100644 --- a/test/SIM_trickified_shared/trickified_project/trickified/.gitignore +++ b/test/SIM_trickified_shared/trickified_project/trickified/.gitignore @@ -1,5 +1,4 @@ build python trick -*.o S_overrides_trickify.mk diff --git a/test/build_config/compare_archives.sh b/test/build_config/compare_archives.sh new file mode 100755 index 000000000..51537dc7b --- /dev/null +++ b/test/build_config/compare_archives.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# Archive-membership parity test (Part C, Phase 2, step 6 / R4 in +# CMAKE_MIGRATION_PLAN.md): builds Trick's core libraries with both `make` +# and CMake on the same machine and diffs `ar t` member-basename sets for +# every one of the nine archives listed in A3. This is a mandatory gate — +# archive membership drift breaks sim link lines subtly (TRICK_LIBS in +# Makefile.common:70), often without a build-time error. +# +# Usage: test/build_config/compare_archives.sh +# Requires: a working `./configure` toolchain, and everything Phase 1/2's +# CMake detection needs (same dependencies as ./configure). +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +# Archive name -> path relative to the make build's lib/ dir vs. the cmake +# build tree (paths differ because cmake keeps per-directory build trees; +# see each CMakeLists.txt's ARCHIVE_OUTPUT_NAME/output directory). +ARCHIVES=( + "libtrick.a:libtrick.a" + "liber7_utils.a:trick_source/er7_utils/liber7_utils.a" + "libtrick_mm.a:trick_source/sim_services/MemoryManager/libtrick_mm.a" + "libtrick_pyip.a:trick_source/trick_swig/libtrick_pyip.a" + "libtrick_comm.a:trick_source/trick_utils/comm/libtrick_comm.a" + "libtrick_connection_handlers.a:trick_source/trick_utils/connection_handlers/libtrick_connection_handlers.a" + "libtrick_math.a:trick_source/trick_utils/math/libtrick_math.a" + "libtrick_optimization.a:trick_source/trick_utils/optimization/libtrick_optimization.a" + "libtrick_units.a:trick_source/trick_utils/units/libtrick_units.a" + "libtrick_var_binary_parser.a:trick_source/trick_utils/var_binary_parser/libtrick_var_binary_parser.a" +) + +# ── 1. make build (skipped if lib/ already has a complete build — CI builds +# this once via the existing autotools job and this script re-uses it) ────── +if [ ! -f lib/libtrick.a ] && [ ! -f lib64/libtrick.a ]; then + ./configure >"$WORKDIR/configure.log" 2>&1 + make -j"$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" no_dp >"$WORKDIR/make.log" 2>&1 || { + echo "make failed; last 200 lines of $WORKDIR/make.log (deleted on exit, so printed here):" >&2 + tail -n 200 "$WORKDIR/make.log" >&2 + exit 1 + } +fi +MAKE_LIB_DIR="lib" +[ -d lib64 ] && MAKE_LIB_DIR="lib64" + +# ── 2. cmake build (three-step bootstrap — see cmake/TrickICG.cmake) ─────── +CMAKE_BUILD_DIR="$WORKDIR/cmake-build" +cmake -S . -B "$CMAKE_BUILD_DIR" >"$WORKDIR/cmake_configure1.log" 2>&1 +cmake --build "$CMAKE_BUILD_DIR" --target trick-ICG trick_io_src_gen -j"$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" \ + >"$WORKDIR/cmake_build_icg.log" 2>&1 +cmake -S . -B "$CMAKE_BUILD_DIR" >"$WORKDIR/cmake_configure2.log" 2>&1 +cmake --build "$CMAKE_BUILD_DIR" -j"$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" >"$WORKDIR/cmake_build.log" 2>&1 || { + # WORKDIR is deleted by the EXIT trap before CI can capture it as an artifact, + # so a bare "see $WORKDIR/cmake_build.log" pointer is useless in CI output — + # print the actual failure here. Full build logs routinely exceed a few + # hundred lines (parallel -j output interleaves per-file compiler + # invocations); tail -n 300 keeps the pointer close enough to the real + # error line(s) without flooding the CI log. + echo "cmake --build failed; last 300 lines of the build log:" >&2 + tail -n 300 "$WORKDIR/cmake_build.log" >&2 + exit 1 +} + +# ── 3. Compare `ar t` member basenames, normalizing away CMake's +# extension-in-object-name convention (Foo.cpp.o vs make's Foo.o) ────────── +normalize_ar() { + ar t "$1" | grep -v '^__\.SYMDEF' | sed -E 's/\.(cpp|cc|c)\.o$/.o/' | sort +} + +FAIL=0 +for pair in "${ARCHIVES[@]}"; do + make_name="${pair%%:*}" + cmake_rel="${pair##*:}" + make_path="$MAKE_LIB_DIR/$make_name" + cmake_path="$CMAKE_BUILD_DIR/$cmake_rel" + + if [ ! -f "$make_path" ]; then + echo "MISSING (make): $make_path" >&2 + FAIL=1 + continue + fi + if [ ! -f "$cmake_path" ]; then + echo "MISSING (cmake): $cmake_path" >&2 + FAIL=1 + continue + fi + + normalize_ar "$make_path" >"$WORKDIR/${make_name}.make.txt" + normalize_ar "$cmake_path" >"$WORKDIR/${make_name}.cmake.txt" + + if diff -u "$WORKDIR/${make_name}.make.txt" "$WORKDIR/${make_name}.cmake.txt" >"$WORKDIR/${make_name}.diff"; then + echo "$make_name: OK ($(wc -l <"$WORKDIR/${make_name}.make.txt") members)" + else + echo "$make_name: MISMATCH" >&2 + cat "$WORKDIR/${make_name}.diff" >&2 + FAIL=1 + fi +done + +if [ "$FAIL" -ne 0 ]; then + echo "Archive parity: FAILED" >&2 + exit 1 +fi +echo "Archive parity: OK (all ${#ARCHIVES[@]} archives match)" diff --git a/test/build_config/compare_config_user.sh b/test/build_config/compare_config_user.sh new file mode 100755 index 000000000..f3f5cf797 --- /dev/null +++ b/test/build_config/compare_config_user.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# Golden-file parity test (Part C, Phase 1, step 6 / D4 in +# CMAKE_MIGRATION_PLAN.md): runs both ./configure and cmake against the same +# tree and diffs the two generated config_user.mk files after normalizing +# away differences that are cosmetic or otherwise known-harmless to +# Makefile.common consumers. Any other difference fails the test. +# +# Usage: test/build_config/compare_config_user.sh [extra cmake -D args...] +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +CONFIG_USER_MK="share/trick/makefiles/config_user.mk" +WORKDIR="$(mktemp -d)" + +# ── 1. Run autoconf's ./configure, preserving any pre-existing config_user.mk ── +# configure writes into the source tree; save/restore so this script is +# non-destructive to a developer's existing build state. +HAD_ORIGINAL=0 +if [ -f "$CONFIG_USER_MK" ]; then + HAD_ORIGINAL=1 + cp "$CONFIG_USER_MK" "$WORKDIR/original_config_user.mk" +fi + +restore_original() { + if [ "$HAD_ORIGINAL" -eq 1 ]; then + cp "$WORKDIR/original_config_user.mk" "$CONFIG_USER_MK" + else + rm -f "$CONFIG_USER_MK" + fi +} +trap 'restore_original; rm -rf "$WORKDIR"' EXIT + +./configure >"$WORKDIR/configure.log" 2>&1 || { + echo "./configure failed; see $WORKDIR/configure.log" >&2 + cat "$WORKDIR/configure.log" >&2 + exit 1 +} +cp "$CONFIG_USER_MK" "$WORKDIR/autoconf_config_user.mk" +restore_original + +# ── 2. Run cmake into a scratch build dir ────────────────────────────────── +CMAKE_BUILD_DIR="$WORKDIR/cmake-build" +cmake -S . -B "$CMAKE_BUILD_DIR" "$@" >"$WORKDIR/cmake.log" 2>&1 || { + echo "cmake configure failed; see $WORKDIR/cmake.log" >&2 + cat "$WORKDIR/cmake.log" >&2 + exit 1 +} +CMAKE_GENERATED="$CMAKE_BUILD_DIR/share/trick/makefiles/config_user.mk" +if [ ! -f "$CMAKE_GENERATED" ]; then + echo "cmake did not produce $CMAKE_GENERATED" >&2 + exit 1 +fi +cp "$CMAKE_GENERATED" "$WORKDIR/cmake_config_user.mk" + +# ── 3. Normalize both files ───────────────────────────────────────────────── +# Accepted deltas: +# - TRICK_GCC_VERSION: autoconf uses "$CC -dumpfullversion -dumpversion"; +# CMake uses CMAKE_CXX_COMPILER_VERSION. Both resolve to the compiler's +# dotted version triplet on every GCC we support; tolerate a trailing +# ".0" CMake sometimes omits (e.g. "11.4" vs "11.4.0"). +# - X_LIB_DIR: confirmed in CI (not just hypothetical dev machines) on the +# macOS runner, which has more than one valid X11 provider installed +# (Homebrew's + Xquartz's /usr/X11); autoconf's AC_PATH_X and CMake's +# FindX11 module each independently pick a different, equally valid +# installation. Both resolve to a linkable libX11, so the value itself +# (not just its presence/absence) is ignored here rather than replicating +# AC_PATH_X's legacy search-order heuristic in CMake. On single-X11- +# provider platforms this value should now match exactly (see +# cmake/TrickPrograms.cmake's IMPLICIT_LINK_DIRECTORIES check) — this +# normalization is a safety net for the multi-provider case, not a mask +# for a real bug. +normalize() { + local infile="$1" + local outfile="$2" + sed -E \ + -e 's/[[:space:]]+$//' \ + -e '/^[[:space:]]*#/d' \ + -e '/^[[:space:]]*$/d' \ + -e 's/^(TRICK_GCC_VERSION[[:space:]]*=[[:space:]]*[0-9]+\.[0-9]+)$/\1.0/' \ + -e 's/^X_LIB_DIR[[:space:]]*=.*/X_LIB_DIR = /' \ + "$infile" | sort >"$outfile" +} + +normalize "$WORKDIR/autoconf_config_user.mk" "$WORKDIR/autoconf_normalized.mk" +normalize "$WORKDIR/cmake_config_user.mk" "$WORKDIR/cmake_normalized.mk" + +# ── 4. Diff ────────────────────────────────────────────────────────────── +if diff -u "$WORKDIR/autoconf_normalized.mk" "$WORKDIR/cmake_normalized.mk"; then + echo "config_user.mk parity: OK" + exit 0 +else + echo "config_user.mk parity: FAILED (see diff above)" >&2 + echo "autoconf: $WORKDIR/autoconf_config_user.mk" >&2 + echo "cmake: $WORKDIR/cmake_config_user.mk" >&2 + exit 1 +fi diff --git a/test/build_config/run_sim_flow.sh b/test/build_config/run_sim_flow.sh new file mode 100755 index 000000000..3a7fb439e --- /dev/null +++ b/test/build_config/run_sim_flow.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# +# Universal acceptance test (CMAKE_MIGRATION_PLAN.md A2/Part E rule 4): a sim built +# with trick-CP against a CMake-installed Trick must compile and run. This drives +# the real installed product interface — trick-CP -> Makefile.common -> config_user.mk +# -> trick-ICG/SWIG — against a staged/installed TRICK_HOME, exactly as an end user +# would. +# +# Usage: run_sim_flow.sh [run_input] +# TRICK_HOME a CMake-installed (or staged) Trick prefix +# sim_dir path to a sim directory containing an S_define +# run_input input file to run, relative to sim_dir (default RUN_test/input.py) +# +set -euo pipefail + +if [ $# -lt 2 ]; then + echo "usage: $0 [run_input]" >&2 + exit 2 +fi + +export TRICK_HOME="$(cd "$1" && pwd)" +SIM_DIR="$(cd "$2" && pwd)" +RUN_INPUT="${3:-RUN_test/input.py}" + +export PATH="${TRICK_HOME}/bin:${PATH}" + +echo "=== sim-flow: TRICK_HOME=${TRICK_HOME}" +echo "=== sim-flow: building ${SIM_DIR} with trick-CP" +cd "${SIM_DIR}" +# Clean any stale build so this genuinely exercises ICG/SWIG/compile against the +# installed Trick, not leftover artifacts from another build system. +trick-CP + +TRICK_HOST_CPU="$(trick-gte TRICK_HOST_CPU)" +SIM_EXE="S_main_${TRICK_HOST_CPU}.exe" +if [ ! -x "${SIM_DIR}/${SIM_EXE}" ]; then + echo "sim-flow FAILED: ${SIM_EXE} was not produced" >&2 + exit 1 +fi + +echo "=== sim-flow: running ${SIM_EXE} ${RUN_INPUT}" +"${SIM_DIR}/${SIM_EXE}" "${RUN_INPUT}" +echo "=== sim-flow: OK" diff --git a/trick_sims/.gitignore b/trick_sims/.gitignore index 1e6c99f95..fa53acd6c 100644 --- a/trick_sims/.gitignore +++ b/trick_sims/.gitignore @@ -5,7 +5,6 @@ S_run_summary send_hs varserver_log log_* -*init_log.csv* chkpnt_* MONTE_RUN_* .S_library* diff --git a/trick_sims/SIM_balloon/models/graphics/.gitignore b/trick_sims/SIM_balloon/models/graphics/.gitignore index fb2fce41a..f213ce824 100644 --- a/trick_sims/SIM_balloon/models/graphics/.gitignore +++ b/trick_sims/SIM_balloon/models/graphics/.gitignore @@ -1,4 +1,4 @@ -!\makefile +!makefile .classpath .project .settings/ diff --git a/trick_sims/SIM_robot/models/graphics/.gitignore b/trick_sims/SIM_robot/models/graphics/.gitignore index 0a76dd934..c0ae5b4bb 100644 --- a/trick_sims/SIM_robot/models/graphics/.gitignore +++ b/trick_sims/SIM_robot/models/graphics/.gitignore @@ -1 +1 @@ -!\makefile +!makefile diff --git a/trick_sims/SIM_satellite/models/Satellite/graphics/.gitignore b/trick_sims/SIM_satellite/models/Satellite/graphics/.gitignore index 21823e21b..1ec1b7e48 100644 --- a/trick_sims/SIM_satellite/models/Satellite/graphics/.gitignore +++ b/trick_sims/SIM_satellite/models/Satellite/graphics/.gitignore @@ -1,3 +1 @@ -*.o Scene - diff --git a/trick_sims/SIM_splashdown/models/CrewModuleGraphics/.gitignore b/trick_sims/SIM_splashdown/models/CrewModuleGraphics/.gitignore index 0a76dd934..c0ae5b4bb 100644 --- a/trick_sims/SIM_splashdown/models/CrewModuleGraphics/.gitignore +++ b/trick_sims/SIM_splashdown/models/CrewModuleGraphics/.gitignore @@ -1 +1 @@ -!\makefile +!makefile diff --git a/trick_sims/SIM_submarine/models/graphics/.gitignore b/trick_sims/SIM_submarine/models/graphics/.gitignore index 0a76dd934..c0ae5b4bb 100644 --- a/trick_sims/SIM_submarine/models/graphics/.gitignore +++ b/trick_sims/SIM_submarine/models/graphics/.gitignore @@ -1 +1 @@ -!\makefile +!makefile diff --git a/trick_sims/SIM_wheelbot/models/Battery/.gitignore b/trick_sims/SIM_wheelbot/models/Battery/.gitignore index c4f4b0097..d8fbd7cd0 100644 --- a/trick_sims/SIM_wheelbot/models/Battery/.gitignore +++ b/trick_sims/SIM_wheelbot/models/Battery/.gitignore @@ -1,6 +1,5 @@ # Ignore compiled objects and libraries lib obj -*.o test/BatteryTest XMLtestReports diff --git a/trick_source/codegen/Interface_Code_Gen/CMakeLists.txt b/trick_source/codegen/Interface_Code_Gen/CMakeLists.txt index ba656b129..b7bb676fa 100644 --- a/trick_source/codegen/Interface_Code_Gen/CMakeLists.txt +++ b/trick_source/codegen/Interface_Code_Gen/CMakeLists.txt @@ -1,62 +1,98 @@ +# trick-ICG: real add_executable, ported from this directory's own Makefile +# (the authority per CMAKE_MIGRATION_PLAN.md Part E.3 — the old CMakeLists.txt +# here belonged to the stale 2019 CMake build and is not trusted). +# +# -DEXTERNAL_BUILD changes PrintAttributes' -sim_services behavior only (see +# PrintAttributes.cpp: printSieClass/printSieEnum/createMapFiles), routing the +# combined class/enum map + SIE resource file into -o's output directory +# instead of hardcoded $TRICK_HOME paths. It has no effect on ordinary +# (non -sim_services) per-sim ICG runs, so it is safe to always define — the +# installed trick-ICG behaves identically for user sims either way. -set ( ICG_SRC - ClassTemplateVisitor - ClassValues - ClassVisitor - CommentSaver - ConstructValues - EnumValues - EnumVisitor - FieldDescription - FieldVisitor - FindTrickICG - HeaderSearchDirs - ICGASTConsumer - PrintAttributes - PrintFileContents10 - PrintFileContentsBase - TranslationUnitVisitor - TypedefVisitor - Utilities - VariableVisitor - main - ../../sim_services/UdUnits/map_trick_units_to_udunits +file(GLOB ICG_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +add_executable(trick-ICG + ${ICG_SOURCES} + ${CMAKE_SOURCE_DIR}/trick_source/sim_services/UdUnits/map_trick_units_to_udunits.cpp ) -set (ICG_CLANGLIBS - -lclangFrontend - -lclangDriver - -lclangSerialization - -lclangParse - -lclangSema - -lclangAnalysis - -lclangEdit - -lclangAST - -lclangLex - -lclangBasic - ) - -try_compile(haveOldLibs "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/CMakeTestFiles/TestICGLinkedLibs.cpp" CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${LLVM_INCLUDE_DIRS}") -if(NOT haveOldLibs) - set (ICG_CLANGLIBS - -lclang-cpp - ) +# C++ standard by clang major, mirroring this directory's Makefile:16-24. +if(_tr_llvm_version_major GREATER_EQUAL 16) + set_property(TARGET trick-ICG PROPERTY CXX_STANDARD 17) +elseif(_tr_llvm_version_major GREATER_EQUAL 10) + set_property(TARGET trick-ICG PROPERTY CXX_STANDARD 14) +else() + set_property(TARGET trick-ICG PROPERTY CXX_STANDARD 11) +endif() +set_property(TARGET trick-ICG PROPERTY CXX_STANDARD_REQUIRED ON) + +target_compile_options(trick-ICG PRIVATE -g -fno-rtti) +target_compile_definitions(trick-ICG PRIVATE + __STDC_CONSTANT_MACROS + __STDC_FORMAT_MACROS + __STDC_LIMIT_MACROS + EXTERNAL_BUILD + LIBCLANG_MAJOR=${_tr_llvm_version_major} +) +string(REGEX MATCH "^[0-9]+\\.([0-9]+)" _tr_llvm_minor_match "${LLVM_VERSION_STRING}") +if(CMAKE_MATCH_1) + target_compile_definitions(trick-ICG PRIVATE LIBCLANG_MINOR=${CMAKE_MATCH_1}) +endif() +string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.([0-9]+)" _tr_llvm_patch_match "${LLVM_VERSION_STRING}") +if(CMAKE_MATCH_1) + target_compile_definitions(trick-ICG PRIVATE LIBCLANG_PATCHLEVEL=${CMAKE_MATCH_1}) +endif() + +target_include_directories(trick-ICG PRIVATE ${LLVM_INCLUDE_DIR}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + target_compile_definitions(trick-ICG PRIVATE TRICK_GCC_VERSION="${GCC_VERSION}") endif() -add_executable( trick-ICG ${ICG_SRC} ) -target_compile_options( trick-ICG PUBLIC -g -DTRICK_VERSION="${TRICK_MAJOR}.${TRICK_MINOR}.${TRICK_TINY}" -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS) -target_compile_options( trick-ICG PUBLIC -DEXTERNAL_BUILD) -target_compile_options( trick-ICG PUBLIC -DLLVM_HOME="${LLVM_ROOT_DIR}") -target_compile_options( trick-ICG PUBLIC -DLIBCLANG_MAJOR=${LLVM_VERSION_MAJOR} -DLIBCLANG_MINOR=${LLVM_VERSION_MINOR} -DLIBCLANG_PATCHLEVEL=${LLVM_VERSION_PATCH}) -target_include_directories( trick-ICG PUBLIC ${UDUNITS2_INCLUDES} ) -target_include_directories( trick-ICG PUBLIC ${LLVM_INCLUDE_DIRS} ) -set_property(SOURCE trick-ICG APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/include/mongoose/mongoose.h) -set_target_properties( trick-ICG PROPERTIES CXX_STANDARD 14) - -target_link_libraries( trick-ICG - ${ICG_CLANGLIBS} - ${LLVM_LDFLAGS} - ${LLVM_LIBRARIES} - ${UDUNITS2_LIBRARIES} +# Only these two files use these extra per-file defines/includes, matching +# the Makefile's targeted CXXFLAGS overrides (lines 74-76). +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/FieldDescription.cpp PROPERTIES + COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/include" +) +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/HeaderSearchDirs.cpp PROPERTIES + COMPILE_DEFINITIONS "LLVM_HOME=\"${LLVM_HOME}\"" ) +set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/main.cpp PROPERTIES + COMPILE_DEFINITIONS "TRICK_VERSION=\"${TRICK_MAJOR}.${TRICK_MINOR}.${TRICK_TINY}\"" +) + +# TR_LLVM_LIBS/TR_LLVM_SYSTEM_LIBS/TR_LLVM_LDFLAGS come from +# cmake/TrickClangLibs.cmake (included at the top level before this +# subdirectory), which already ran `llvm-config --libs/--system-libs/--ldflags` +# and filtered --system-libs per platform (e.g. stripping Fedora's spurious +# -ledit on Linux) for its own sanity try_compile — reuse them here instead of +# invoking llvm-config and re-deriving the same filter a second time. +separate_arguments(_tr_icg_clanglibs_list NATIVE_COMMAND "${ICG_CLANGLIBS}") +separate_arguments(_tr_icg_llvm_libs_list NATIVE_COMMAND "${TR_LLVM_LIBS}") +separate_arguments(_tr_icg_llvm_ldflags_list NATIVE_COMMAND "${TR_LLVM_LDFLAGS}") +separate_arguments(_tr_icg_llvm_system_libs_list NATIVE_COMMAND "${TR_LLVM_SYSTEM_LIBS}") + +target_link_libraries(trick-ICG PRIVATE ${_tr_icg_clanglibs_list} ${_tr_icg_llvm_ldflags_list} ${_tr_icg_llvm_libs_list} ${_tr_icg_llvm_system_libs_list} Trick::udunits2) +target_link_directories(trick-ICG PRIVATE ${LLVM_LIB_DIR}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + if(_tr_llvm_version_major GREATER_EQUAL 16) + target_link_libraries(trick-ICG PRIVATE -lc++abi -lclang-cpp) + else() + target_link_libraries(trick-ICG PRIVATE -lc++abi) + endif() + # CMake's own automatic rpath handling already embeds an LC_RPATH for + # LLVM_LIB_DIR here, since we linked against libraries there via + # target_link_directories; the Makefile's explicit install_name_tool step + # is therefore usually redundant on this toolchain (but harmless to skip + # if it fails, e.g. because the rpath is already present). + add_custom_command(TARGET trick-ICG POST_BUILD + COMMAND bash -c "install_name_tool -add_rpath '${LLVM_LIB_DIR}' '$' 2>/dev/null; true" + VERBATIM + ) +endif() +# UDUNITS_HOME may be a non-system prefix; keep the build-time rpath to +# libudunits2 in the installed binary (CMake drops build rpath at install by +# default) instead of the makefile's literal -Wl,-rpath. +set_target_properties(trick-ICG PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) diff --git a/trick_source/data_products/.gitignore b/trick_source/data_products/.gitignore index 8826e6b24..92083e8ca 100644 --- a/trick_source/data_products/.gitignore +++ b/trick_source/data_products/.gitignore @@ -1,3 +1,2 @@ fermi-ware -Apps/trkConvert/*.o Apps/trkConvert/trkConvert diff --git a/trick_source/data_products/Apps/ExternalPrograms/CMakeLists.txt b/trick_source/data_products/Apps/ExternalPrograms/CMakeLists.txt new file mode 100644 index 000000000..0e6910605 --- /dev/null +++ b/trick_source/data_products/Apps/ExternalPrograms/CMakeLists.txt @@ -0,0 +1,13 @@ +# DP "external program" plugin .so's — ported from this directory's own +# makefile (the authority). Only dp_test.so and dp_subtract.so are actually +# built by `make all` (OBJECTS0's other targets, e.g. dp_lvlh_attitude.so, +# are real rules but nothing in the makefile's dependency graph reaches +# them — `objects: $(OBJECTS1)` where OBJECTS1 = dp_test.so dp_subtract.so +# only; the fuller OBJECTS0 list is commented out). No stale 2019 +# CMakeLists.txt existed for this directory. +add_library(dp_test MODULE dp_test.c) +add_library(dp_subtract MODULE dp_subtract.c) +set_target_properties(dp_test dp_subtract PROPERTIES + PREFIX "" + SUFFIX ".so" +) diff --git a/trick_source/data_products/Apps/Trk2csv/CMakeLists.txt b/trick_source/data_products/Apps/Trk2csv/CMakeLists.txt new file mode 100644 index 000000000..6c556cef5 --- /dev/null +++ b/trick_source/data_products/Apps/Trk2csv/CMakeLists.txt @@ -0,0 +1,20 @@ +# trick-trk2ascii — ported from this directory's own makefile (the +# authority). No stale 2019 CMakeLists.txt existed for this directory. +# +# The makefile's link line is `-L../../lib_ -llog -lvar -L$(TRICK_LIB_DIR) +# -ltrick_units`: -L search paths are cumulative in link order, so +# `-ltrick_units` actually resolves against data_products/units's own +# libtrick_units.a (the first -L given) rather than trick_utils/units' +# same-named archive at TRICK_LIB_DIR — confirmed by nm against a real +# make build's liblog.a/libtrick_units.a in trick_source/data_products/ +# lib_Darwin_25 (TrickBinary.cpp calls map_trick_units_to_udunits(), which +# only data_products/units/map_trick_units_to_udunits.cpp defines; the core +# trick_utils/units archive does not). Link dp_units, not trick_units. +add_executable(trick-trk2ascii trk2ascii.cpp) +target_include_directories(trick-trk2ascii PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../..) +target_link_libraries(trick-trk2ascii PRIVATE dp_log dp_var dp_units) +if(APPLE) + target_link_libraries(trick-trk2ascii PRIVATE -lc++abi) +endif() + +install(TARGETS trick-trk2ascii RUNTIME DESTINATION bin) diff --git a/trick_source/data_products/CMakeLists.txt b/trick_source/data_products/CMakeLists.txt index 63b3380a7..6fa3ff8f9 100644 --- a/trick_source/data_products/CMakeLists.txt +++ b/trick_source/data_products/CMakeLists.txt @@ -1,11 +1,28 @@ - +# data_products: ported from this directory's own makefile (the authority). +# LIBDIRS always build; fermi-ware only exists on some checkouts (this one +# doesn't have it — matches DPX's FXPLOT gate below); APPDIRS = DPX, +# Apps/Trk2csv, Apps/ExternalPrograms. add_subdirectory(Var) add_subdirectory(Log) add_subdirectory(EQParse) add_subdirectory(units) -if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/fermi-ware/CMakeLists.txt ) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/fermi-ware/CMakeLists.txt) add_subdirectory(fermi-ware) endif() add_subdirectory(DPX) +add_subdirectory(Apps/Trk2csv) +add_subdirectory(Apps/ExternalPrograms) + +# Umbrella target for the Phase 3 `stage` install target to depend on. +add_custom_target(trick-data-products) +add_dependencies(trick-data-products + dp_var dp_log dp_eqparse dp_units + DPM DPC dpv_utils + trick-trk2ascii + dp_test dp_subtract +) +if(USE_X_WINDOWS) + add_dependencies(trick-data-products trick-gxplot) +endif() diff --git a/trick_source/data_products/DPX/APPS/FXPLOT/CMakeLists.txt b/trick_source/data_products/DPX/APPS/FXPLOT/CMakeLists.txt index 787e80865..8c67cfd52 100644 --- a/trick_source/data_products/DPX/APPS/FXPLOT/CMakeLists.txt +++ b/trick_source/data_products/DPX/APPS/FXPLOT/CMakeLists.txt @@ -1,23 +1,77 @@ +# trick-fxplot — the Motif/fermi-ware plotter, ported from this directory's own +# makefile (the authority; the 2019 stale CMakeLists.txt is untrusted per +# CMAKE_MIGRATION_PLAN.md A4). Sibling of GXPLOT (../GXPLOT/CMakeLists.txt) — +# same structure and the same GNU-ld single-pass link-order care. +# +# UNVERIFIED: fermi-ware ("fermi-ware/") is a NASA-internal tree absent from +# this checkout, so this whole target is gated (data_products/DPX/CMakeLists.txt +# only add_subdirectory's APPS/FXPLOT when fermi-ware/CMakeLists.txt exists) and +# has never been built here. The `fermi` link target below is the name the +# makefile implies (it links fermi-ware's `libfermi.a`); whoever restores +# fermi-ware must ensure its CMakeLists provides a target producing libfermi.a +# (ARCHIVE_OUTPUT_NAME fermi). Motif has no X11::Xm imported target (Motif is +# not core X11), so it stays on MOTIF_HOME, matching the makefile. +set(FXPLOT_SRC + parse_format.c + post_dialog.c + fermi_view.cpp + fxplot.cpp + curve_view_node.cpp + plot_view_node.cpp + table_view_node.cpp + page_view_node.cpp + product_view_node.cpp +) -set( FXPLOT_SRC - curve_view_node - fermi_view - fxplot - page_view_node - parse_format - plot_view_node - post_dialog - product_view_node - table_view_node +add_executable(trick-fxplot ${FXPLOT_SRC}) +target_include_directories(trick-fxplot PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/trick_source/data_products/fermi-ware ) +if(MOTIF_HOME) + target_include_directories(trick-fxplot PRIVATE ${MOTIF_HOME}/include) +endif() -add_executable( trick-fxplot ${FXPLOT_SRC}) -target_include_directories( trick-fxplot PUBLIC ${X11_X11_INCLUDE_PATH} ) -target_include_directories( trick-fxplot PUBLIC ${LIBXML2_INCLUDE_DIR} ) -target_include_directories( trick-fxplot PUBLIC ../.. ) -target_include_directories( trick-fxplot PUBLIC ../../../fermi-ware ) -target_link_libraries( trick-fxplot DPC DPM dp_log dp_var dpv_utils fermiware dp_eqparse dp_units - -ldl - ${X11_Xt_LIB} ${X11_X11_LIB} ${MOTIF_LIBRARIES} - ${UDUNITS2_LIBRARIES} ${LIBXML2_LIBRARIES}) +# Link order matters (GNU ld resolves left-to-right in one pass, so a library +# must follow whatever consumes its symbols). Mirrors the makefile's final link +# line: OBJECT_FILES then ALL_LIBS (DPX_LIBS FERMI_WARE_LIB DP_LIBS +# TRICK_UNIT_LIBS LIBXML HDF5_LIB -ldl UDUNITS_LDFLAGS) then XLIBS (Motif -lXm +# -lXt -lX11) then LIBRTDEF (-lrt on Linux). See ../GXPLOT/CMakeLists.txt for +# the same reasoning and the macOS-vs-Linux linker-strictness note. +set(_tr_fxplot_libs + DPC + DPM + fermi + dp_log dp_var dp_eqparse dp_units + LibXml2::LibXml2 +) +if(HDF5_HOME) + list(APPEND _tr_fxplot_libs trick::hdf5) +endif() +list(APPEND _tr_fxplot_libs + dl + Trick::udunits2 +) +# Motif (-lXm) has no imported target; link it from MOTIF_HOME like the makefile. +if(MOTIF_HOME AND NOT MOTIF_HOME STREQUAL "/usr") + list(APPEND _tr_fxplot_libs -L${MOTIF_HOME}/lib) +endif() +list(APPEND _tr_fxplot_libs + -lXm + X11::Xt + X11::X11 +) +if(APPLE) + list(APPEND _tr_fxplot_libs -lc++abi) +else() + list(APPEND _tr_fxplot_libs rt) +endif() +target_link_libraries(trick-fxplot PRIVATE ${_tr_fxplot_libs}) +# UDUNITS_HOME may be a non-system prefix; keep the build-time rpath to +# libudunits2 in the installed binary (CMake drops build rpath at install by +# default) instead of the makefile's literal -Wl,-rpath. +set_target_properties(trick-fxplot PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) +install(TARGETS trick-fxplot RUNTIME DESTINATION bin) diff --git a/trick_source/data_products/DPX/APPS/GXPLOT/CMakeLists.txt b/trick_source/data_products/DPX/APPS/GXPLOT/CMakeLists.txt index 68dc33136..7900251ed 100644 --- a/trick_source/data_products/DPX/APPS/GXPLOT/CMakeLists.txt +++ b/trick_source/data_products/DPX/APPS/GXPLOT/CMakeLists.txt @@ -1,22 +1,72 @@ +# trick-gxplot — ported from this directory's own makefile (the authority). +# parse_format.c was missing from the stale 2019 source list (Part A4: the +# stale files are hints, not the authority) — without it gp_view.cpp's +# parse_format() calls fail to link. +# +# HDF5_LIB / -lc++abi / DPC listed twice mirror the makefile's own ALL_LIBS + +# trailing ${CONTROLLER_LIBS} -lDPV (a real circular DPC<->DPV dependency the +# make link line works around by repeating -lDPC after -lDPV). +# +# -ltrick_units resolves against data_products/units's own libtrick_units.a, +# not trick_utils/units' same-named archive — see the comment in +# ../../Apps/Trk2csv/CMakeLists.txt for the -L-search-order evidence. Link +# dp_units, not trick_units. +set(GXPLOT_SRC + parse_format.c + gp_view.cpp + gp_colors.cpp + gp_utilities.cpp + gp_version.cpp + gxplot.cpp + gp_view_curve_node.cpp + gp_view_plot_node.cpp + gp_view_page_node.cpp + gp_view_product_node.cpp +) -set( GXPLOT_SRC - gp_colors - gp_utilities - gp_version - gp_view - gp_view_curve_node - gp_view_page_node - gp_view_plot_node - gp_view_product_node - gxplot +add_executable(trick-gxplot ${GXPLOT_SRC}) +# X11/LibXml2 include dirs come from the X11::X11 / LibXml2::LibXml2 imported +# targets linked below (their INTERFACE_INCLUDE_DIRECTORIES), so they are not +# repeated here. +target_include_directories(trick-gxplot PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_SOURCE_DIR}/include ) -add_executable( trick-gxplot ${GXPLOT_SRC}) -target_include_directories( trick-gxplot PUBLIC ${X11_X11_INCLUDE_PATH} ) -target_include_directories( trick-gxplot PUBLIC ${LIBXML2_INCLUDE_DIR} ) -target_include_directories( trick-gxplot PUBLIC ../.. ) -target_link_libraries( trick-gxplot DPC DPM dp_log dp_var dpv_utils dp_eqparse dp_units - -ldl - ${X11_Xt_LIB} ${X11_X11_LIB} - ${UDUNITS2_LIBRARIES} ${LIBXML2_LIBRARIES}) +# Link order matters here: GNU ld (default on Linux) resolves symbols in a +# single left-to-right pass, so a library must appear *after* whatever +# consumes its symbols. This mirrors the makefile's ALL_LIBS + final link +# line order exactly (CONTROLLER_LIBS MODEL_LIBS DP_LIBS HDF5_LIB -ldl +# UDUNITS_LDFLAGS XLIBS LIBRTDEF CONTROLLER_LIBS -lDPV) — a prior version of +# this file used a separate target_link_options() call for UDUNITS_LDFLAGS, +# which does not guarantee it lands after the DPC/DPM/dp_units archives that +# actually need it, and silently linked fine on macOS (ld64's linker is far +# more forgiving of ordering) while failing with "undefined reference to +# `ut_parse'" etc. on Linux. +set(_tr_gxplot_libs + DPC + DPM + dp_log dp_var dp_eqparse dp_units +) +if(HDF5_HOME) + list(APPEND _tr_gxplot_libs trick::hdf5) +endif() +list(APPEND _tr_gxplot_libs + dl + Trick::udunits2 + X11::Xt X11::X11 + LibXml2::LibXml2 +) +if(APPLE) + list(APPEND _tr_gxplot_libs -lc++abi) +else() + list(APPEND _tr_gxplot_libs rt) +endif() +list(APPEND _tr_gxplot_libs DPC dpv_utils) +target_link_libraries(trick-gxplot PRIVATE ${_tr_gxplot_libs}) +# UDUNITS_HOME may be a non-system prefix; keep the build-time rpath to +# libudunits2 in the installed binary (CMake drops build rpath at install by +# default) instead of the makefile's literal -Wl,-rpath. +set_target_properties(trick-gxplot PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) +install(TARGETS trick-gxplot RUNTIME DESTINATION bin) diff --git a/trick_source/data_products/DPX/CMakeLists.txt b/trick_source/data_products/DPX/CMakeLists.txt index 1209cad47..cf9e3d845 100644 --- a/trick_source/data_products/DPX/CMakeLists.txt +++ b/trick_source/data_products/DPX/CMakeLists.txt @@ -1,8 +1,12 @@ - +# ported from this directory's own makefile: LIBDIRS always build; APPDIRS +# (GXPLOT, and FXPLOT if fermi-ware/ exists) only when USE_X_WINDOWS. add_subdirectory(DPM) add_subdirectory(DPC) add_subdirectory(DPV/UTILS) -add_subdirectory(APPS/GXPLOT) -if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../fermi-ware/CMakeLists.txt ) - add_subdirectory(APPS/FXPLOT) + +if(USE_X_WINDOWS) + add_subdirectory(APPS/GXPLOT) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../fermi-ware/CMakeLists.txt) + add_subdirectory(APPS/FXPLOT) + endif() endif() diff --git a/trick_source/data_products/DPX/DPC/CMakeLists.txt b/trick_source/data_products/DPX/DPC/CMakeLists.txt index fa9985d08..f65f33542 100644 --- a/trick_source/data_products/DPX/DPC/CMakeLists.txt +++ b/trick_source/data_products/DPX/DPC/CMakeLists.txt @@ -1,20 +1,24 @@ - -set( DPC_SRC - DPC_TimeCstrDataStream - DPC_UnitConvDataStream - DPC_datastream_supplier - DPC_delta_curve - DPC_delta_plot - DPC_page - DPC_plot - DPC_product - DPC_standard_plot - DPC_std_curve - DPC_table +# libDPC.a — ported from this directory's own makefile (the authority). +set(DPC_SRC + DPC_TimeCstrDataStream.cpp + DPC_UnitConvDataStream.cpp + DPC_datastream_supplier.cpp + DPC_delta_curve.cpp + DPC_delta_plot.cpp + DPC_page.cpp + DPC_plot.cpp + DPC_product.cpp + DPC_standard_plot.cpp + DPC_std_curve.cpp + DPC_table.cpp ) -add_library( DPC STATIC ${DPC_SRC}) -target_include_directories( DPC PUBLIC ${LIBXML2_INCLUDE_DIR} ) -target_include_directories( DPC PUBLIC ${UDUNITS2_INCLUDES} ) -target_include_directories( DPC PUBLIC .. ) - +add_library(DPC STATIC ${DPC_SRC}) +target_include_directories(DPC PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_SOURCE_DIR}/include +) +# PRIVATE: libxml2 headers are a compile-only need (static archive → no link +# propagation); LibXml2::LibXml2 supplies the include dirs. +target_link_libraries(DPC PRIVATE LibXml2::LibXml2 Trick::udunits2) diff --git a/trick_source/data_products/DPX/DPM/CMakeLists.txt b/trick_source/data_products/DPX/DPM/CMakeLists.txt index dae9c46bf..3713f2bf7 100644 --- a/trick_source/data_products/DPX/DPM/CMakeLists.txt +++ b/trick_source/data_products/DPX/DPM/CMakeLists.txt @@ -1,27 +1,32 @@ - -set( DPM_SRC - DPM_attribute - DPM_axis - DPM_column - DPM_component - DPM_curve - DPM_extfn - DPM_inputs - DPM_measurement - DPM_outputs - DPM_page - DPM_parse_tree - DPM_product - DPM_relation - DPM_run - DPM_session - DPM_table - DPM_time_constraints - DPM_var +# libDPM.a — ported from this directory's own makefile (the authority). +set(DPM_SRC + DPM_attribute.cpp + DPM_axis.cpp + DPM_column.cpp + DPM_component.cpp + DPM_curve.cpp + DPM_extfn.cpp + DPM_inputs.cpp + DPM_measurement.cpp + DPM_outputs.cpp + DPM_page.cpp + DPM_parse_tree.cpp + DPM_product.cpp + DPM_relation.cpp + DPM_run.cpp + DPM_session.cpp + DPM_table.cpp + DPM_time_constraints.cpp + DPM_var.cpp ) -add_library( DPM STATIC ${DPM_SRC}) -target_include_directories( DPM PUBLIC ${LIBXML2_INCLUDE_DIR} ) -target_include_directories( DPM PUBLIC ${UDUNITS2_INCLUDES} ) -target_include_directories( DPM PUBLIC .. ) - +add_library(DPM STATIC ${DPM_SRC}) +target_include_directories(DPM PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_SOURCE_DIR}/include +) +# PRIVATE: libxml2 headers are a compile-only need of DPM's own sources; a +# static archive propagates no link, so this just supplies the include dirs +# (via LibXml2::LibXml2's INTERFACE_INCLUDE_DIRECTORIES). +target_link_libraries(DPM PRIVATE LibXml2::LibXml2 Trick::udunits2) diff --git a/trick_source/data_products/DPX/DPV/UTILS/CMakeLists.txt b/trick_source/data_products/DPX/DPV/UTILS/CMakeLists.txt index b5a1f7cba..78e59fa7d 100644 --- a/trick_source/data_products/DPX/DPV/UTILS/CMakeLists.txt +++ b/trick_source/data_products/DPX/DPV/UTILS/CMakeLists.txt @@ -1,7 +1,4 @@ - -set( DPV_UTILS_SRC - DPV_textbuffer -) - -add_library( dpv_utils STATIC ${DPV_UTILS_SRC}) - +# libDPV.a — ported from this directory's own makefile (the authority). +add_library(dpv_utils STATIC DPV_textbuffer.cpp) +target_include_directories(dpv_utils PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../..) +set_target_properties(dpv_utils PROPERTIES ARCHIVE_OUTPUT_NAME DPV) diff --git a/trick_source/data_products/DPX/test/unit_test/.gitignore b/trick_source/data_products/DPX/test/unit_test/.gitignore index bb6e1d856..d9457e18a 100644 --- a/trick_source/data_products/DPX/test/unit_test/.gitignore +++ b/trick_source/data_products/DPX/test/unit_test/.gitignore @@ -1,4 +1,3 @@ -*.o DPC_test DPM_test DS_test diff --git a/trick_source/data_products/DPX/test/unit_test/makefile b/trick_source/data_products/DPX/test/unit_test/makefile index 364e79e54..e9ae007b2 100644 --- a/trick_source/data_products/DPX/test/unit_test/makefile +++ b/trick_source/data_products/DPX/test/unit_test/makefile @@ -5,16 +5,24 @@ RM = rm -rf CC = gcc CPP = g++ -DPX_DIR = ${TRICK_HOME}/trick_source/data_products/DPX -DS_DIR = ${TRICK_HOME}/trick_source/data_products +# TRICK_SRC_HOME is separate from TRICK_HOME so this test can run with +# TRICK_HOME pointed at a staged (out-of-source) CMake install while still +# finding data_products' headers, which only exist in the source tree — a +# CMake build compiles in place from source without copying headers into +# the build tree. Defaults to TRICK_HOME, preserving in-source `make` +# behavior exactly (TRICK_HOME already is the source root there). +TRICK_SRC_HOME ?= ${TRICK_HOME} + +DPX_DIR = ${TRICK_SRC_HOME}/trick_source/data_products/DPX +DS_DIR = ${TRICK_SRC_HOME}/trick_source/data_products INCDIRS = -I$(GTEST_HOME)/include \ -I/usr/include/libxml2 \ -I/usr/X11R6/include \ -I${TRICK_HOME}/include \ - -I${TRICK_HOME}/trick_source/data_products \ - -I${TRICK_HOME}/trick_source/data_products/Apps/FPlot \ - -I${TRICK_HOME}/trick_source/data_products/DPX \ + -I${DS_DIR} \ + -I${DS_DIR}/Apps/FPlot \ + -I${DPX_DIR} \ ${MOTIF_INCDIR} CFLAGS = -g -Wall -Wextra ${INCDIRS} $(UDUNITS_INCLUDES) @@ -23,6 +31,19 @@ LIB_DPX_DIR = ${DPX_DIR}/lib_${TRICK_HOST_CPU} LIB_DS_DIR = ${DS_DIR}/lib_${TRICK_HOST_CPU} # Save number plus first decimal place. +# Per-library search dirs, each independently overridable and defaulting to +# the shared lib_$(TRICK_HOST_CPU) dirs above (identical to historical +# behavior under in-source `make`). A CMake-driven test run overrides these +# individually, since CMake builds each library into its own target output +# directory (DPM/libDPM.a, DPC/libDPC.a, Log/liblog.a, ...) rather than one +# shared directory. +LIB_LOG_DIR = ${LIB_DS_DIR} +LIB_VAR_DIR = ${LIB_DS_DIR} +LIB_EQPARSE_DIR = ${LIB_DS_DIR} +LIB_UNITS_DIR = ${LIB_DS_DIR} +LIB_DPM_DIR = ${LIB_DPX_DIR} +LIB_DPC_DIR = ${LIB_DPX_DIR} + ifeq ($(TRICK_HOST_TYPE), Linux) LIBRTDEF = -lrt else @@ -42,13 +63,15 @@ endif GTEST_LIBS = -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -DP_LIBS = -L${TRICK_HOME}/trick_source/data_products/lib_${TRICK_HOST_CPU} \ - -llog -lvar -leqparse -ltrick_units +DP_LIBS = -L${LIB_LOG_DIR} -llog \ + -L${LIB_VAR_DIR} -lvar \ + -L${LIB_EQPARSE_DIR} -leqparse \ + -L${LIB_UNITS_DIR} -ltrick_units MODEL_LIBS = -lxml2 \ - -L${DPX_DIR}/lib_${TRICK_HOST_CPU} -lDPM \ - -L${TRICK_HOME}/trick_source/data_products/lib_${TRICK_HOST_CPU} -ltrick_units \ + -L${LIB_DPM_DIR} -lDPM \ + -L${LIB_UNITS_DIR} -ltrick_units \ ${GTEST_LIBS} -lpthread -ludunits2 ${UDUNITS_LDFLAGS} -CONTROLLER_LIBS = -lDPC \ +CONTROLLER_LIBS = -L${LIB_DPC_DIR} -lDPC \ ${MODEL_LIBS} ${DP_LIBS} \ ${XLIBS} ${LIBRTDEF} \ -L/usr/lib64 -L/usr/lib -lz ${HDF5_LIB} @@ -76,27 +99,26 @@ test : $(TESTS) ./DPM_test --gtest_output=xml:${TRICK_HOME}/trick_test/DataProducts_M.xml ./DS_test --gtest_output=xml:${TRICK_HOME}/trick_test/DataStream.xml -DPM_test: DPM_test.o ${LIB_DPX_DIR}/libDPM.a +DPM_test: DPM_test.o ${LIB_DPM_DIR}/libDPM.a @echo "===== Making DPM_test =====" ${CPP} -o $@ DPM_test.o ${MODEL_LIBS} -DPC_test: DPC_test.o test_view.o ${LIB_DPX_DIR}/libDPM.a ${LIB_DPX_DIR}/libDPC.a +DPC_test: DPC_test.o test_view.o ${LIB_DPM_DIR}/libDPM.a ${LIB_DPC_DIR}/libDPC.a @echo "===== Making DPC_test =====" ${CPP} -o $@ DPC_test.o test_view.o ${CONTROLLER_LIBS} -DS_test: DS_test.o ${LIB_DS_DIR}/liblog.a - @echo "===== Making DS_test ======" +DS_test: DS_test.o ${LIB_LOG_DIR}/liblog.a + @echo "===== Making DS_test ======" ${CPP} -o $@ DS_test.o ${DS_LIBS} -${LIB_DPX_DIR}/libDPM.a: +${LIB_DPM_DIR}/libDPM.a: @echo "===== Making libDPM.a =====" $(MAKE) -C ${DPX_DIR}/DPM -${LIB_DPX_DIR}/libDPC.a: +${LIB_DPC_DIR}/libDPC.a: @echo "===== Making libDPC.a =====" $(MAKE) -C ${DPX_DIR}/DPC clean: ${RM} *~ ${RM} $(TESTS) *.o - diff --git a/trick_source/data_products/EQParse/CMakeLists.txt b/trick_source/data_products/EQParse/CMakeLists.txt index 54b79a046..3aa6846cf 100644 --- a/trick_source/data_products/EQParse/CMakeLists.txt +++ b/trick_source/data_products/EQParse/CMakeLists.txt @@ -1,19 +1,23 @@ - -set ( DP_EQPARSE_SRC - eqparse - eqparse_chkvalid - eqparse_error - eqparse_evaluate - eqparse_fillno - eqparse_funcsub - eqparse_math - eqparse_negcheck - eqparse_operatorcheck - eqparse_postfix - eqparse_stack - eqparse_takeinput - eqparse_test +# libeqparse.a — ported from this directory's own makefile (the authority). +# eqparse_test.c is a standalone smoke-test executable's source, NOT part of +# the library (makefile: E_C_SRC = $(filter-out eqparse_test.c, $(wildcard +# *.c))) — the stale 2019 CMakeLists.txt included it in the library, which +# is wrong (see CMAKE_MIGRATION_PLAN.md Part A4: the stale files are hints, +# not the authority). +set(DP_EQPARSE_SRC + eqparse.c + eqparse_chkvalid.c + eqparse_error.c + eqparse_evaluate.c + eqparse_fillno.c + eqparse_funcsub.c + eqparse_math.c + eqparse_negcheck.c + eqparse_operatorcheck.c + eqparse_postfix.c + eqparse_stack.c + eqparse_takeinput.c ) -add_library( dp_eqparse STATIC ${DP_EQPARSE_SRC}) - +add_library(dp_eqparse STATIC ${DP_EQPARSE_SRC}) +set_target_properties(dp_eqparse PROPERTIES ARCHIVE_OUTPUT_NAME eqparse) diff --git a/trick_source/data_products/Log/CMakeLists.txt b/trick_source/data_products/Log/CMakeLists.txt index 9e12cbed8..fc45070ee 100644 --- a/trick_source/data_products/Log/CMakeLists.txt +++ b/trick_source/data_products/Log/CMakeLists.txt @@ -1,24 +1,40 @@ - -# need to add TrickHDF5 if HDF5 found -set ( DP_LOG_SRC - Csv - DataStream - DataStreamFactory - DataStreamGroup - Delta - ExternalProgram - MatLab - MatLab4 - TrickBinary - log - multiLog - parseLogHeader - trick_byteswap +# liblog.a — ported from this directory's own makefile (the authority). +# TrickHDF5.cpp/DataStreamFactory.cpp's extra -DHDF5/-I only apply when HDF5 +# was detected (makefile:24-28), mirrored below with per-file overrides. +set(DP_LOG_SRC + Csv.cpp + DataStream.cpp + DataStreamFactory.cpp + DataStreamGroup.cpp + Delta.cpp + ExternalProgram.cpp + MatLab.cpp + MatLab4.cpp + TrickBinary.cpp + log.cpp + multiLog.cpp + parseLogHeader.cpp + trick_byteswap.cpp ) -# TrickHDF5 - -add_library( dp_log STATIC ${DP_LOG_SRC}) -target_include_directories( dp_log PUBLIC .. ) -target_include_directories( dp_log PUBLIC ${UDUNITS2_INCLUDES} ) +if(HDF5_HOME) + list(APPEND DP_LOG_SRC TrickHDF5.cpp) +endif() +add_library(dp_log STATIC ${DP_LOG_SRC}) +target_include_directories(dp_log PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_SOURCE_DIR}/include +) +target_link_libraries(dp_log PRIVATE Trick::udunits2) +set_target_properties(dp_log PROPERTIES ARCHIVE_OUTPUT_NAME log) +# Deliberately per-source rather than target_link_libraries(... trick::hdf5): +# source properties can't consume a target's usage requirements, and this +# scoping must match the Makefile's file-local override exactly (link-time +# HDF5 libs come from trick::hdf5 on the FXPLOT/GXPLOT executables that link +# dp_log). +if(HDF5_HOME) + set_source_files_properties(TrickHDF5.cpp DataStreamFactory.cpp PROPERTIES + COMPILE_OPTIONS "-I${HDF5_HOME}/include;-DHDF5" + ) +endif() diff --git a/trick_source/data_products/Var/CMakeLists.txt b/trick_source/data_products/Var/CMakeLists.txt index d78198f0d..ea148a945 100644 --- a/trick_source/data_products/Var/CMakeLists.txt +++ b/trick_source/data_products/Var/CMakeLists.txt @@ -1 +1,4 @@ -add_library( dp_var STATIC var ) +# libvar.a — ported from this directory's own makefile (the authority). +add_library(dp_var STATIC var.cpp) +target_include_directories(dp_var PRIVATE ${CMAKE_SOURCE_DIR}/include) +set_target_properties(dp_var PROPERTIES ARCHIVE_OUTPUT_NAME var) diff --git a/trick_source/data_products/units/CMakeLists.txt b/trick_source/data_products/units/CMakeLists.txt index 8f55c7a00..bf66c5b40 100644 --- a/trick_source/data_products/units/CMakeLists.txt +++ b/trick_source/data_products/units/CMakeLists.txt @@ -1,10 +1,12 @@ - -set ( DP_UNITS_SRC - init_units_system - map_trick_units_to_udunits - units_conv +# libtrick_units.a (data_products' own copy — unrelated to and not linked +# against trick_source/trick_utils/units' same-named archive; see this +# directory's makefile, whose output nothing else in the make flow +# references). Built anyway to match `make all`'s artifact set. +add_library(dp_units STATIC + init_units_system.cpp + map_trick_units_to_udunits.cpp + units_conv.c ) - -add_library( dp_units STATIC ${DP_UNITS_SRC}) -target_include_directories( dp_units PUBLIC ${UDUNITS2_INCLUDES} ) - +target_include_directories(dp_units PRIVATE ${CMAKE_SOURCE_DIR}/include) +target_link_libraries(dp_units PRIVATE Trick::udunits2) +set_target_properties(dp_units PROPERTIES ARCHIVE_OUTPUT_NAME trick_units) diff --git a/trick_source/er7_utils/CMakeLists.txt b/trick_source/er7_utils/CMakeLists.txt index b89cda4f4..42ecf446d 100644 --- a/trick_source/er7_utils/CMakeLists.txt +++ b/trick_source/er7_utils/CMakeLists.txt @@ -1,72 +1,79 @@ - +# liber7_utils.a. Source list cross-checked against a real `make` build's +# lib/liber7_utils.a member set (verified 2026-07-06) — matches exactly. +# io_src objects come from TrickICG.cmake's ER7_IO_SOURCES partition (see +# cmake/scripts/GenerateIOSrcList.cmake). set( ER7_UTILS_SRC - integration/abm4/src/abm4_first_order_ode_integrator - integration/abm4/src/abm4_integrator_constructor - integration/abm4/src/abm4_second_order_ode_integrator - integration/beeman/src/beeman_integrator_constructor - integration/beeman/src/beeman_second_order_ode_integrator - integration/core/src/base_integration_group - integration/core/src/bogus_integration_controls - integration/core/src/first_order_ode_integrator - integration/core/src/integration_controls - integration/core/src/integration_messages - integration/core/src/integrator_constructor - integration/core/src/integrator_constructor_factory - integration/core/src/integrator_result_merger - integration/core/src/integrator_result_merger_container - integration/core/src/left_quaternion_functions - integration/core/src/priming_first_order_ode_integrator - integration/core/src/priming_integration_controls - integration/core/src/priming_integrator_constructor - integration/core/src/priming_second_order_ode_integrator - integration/core/src/second_order_ode_integrator - integration/core/src/single_cycle_integration_controls - integration/core/src/standard_integration_controls - integration/euler/src/euler_first_order_ode_integrator - integration/euler/src/euler_integrator_constructor - integration/euler/src/euler_second_order_ode_integrator - integration/mm4/src/mm4_integrator_constructor - integration/mm4/src/mm4_second_order_ode_integrator - integration/nl2/src/nl2_integrator_constructor - integration/nl2/src/nl2_second_order_ode_integrator - integration/position_verlet/src/position_verlet_integrator_constructor - integration/position_verlet/src/position_verlet_second_order_ode_integrator - integration/rk2_heun/src/rk2_heun_first_order_ode_integrator - integration/rk2_heun/src/rk2_heun_integrator_constructor - integration/rk2_heun/src/rk2_heun_second_order_ode_integrator - integration/rk2_midpoint/src/rk2_midpoint_first_order_ode_integrator - integration/rk2_midpoint/src/rk2_midpoint_integrator_constructor - integration/rk2_midpoint/src/rk2_midpoint_second_order_ode_integrator - integration/rk4/src/rk4_first_order_ode_integrator - integration/rk4/src/rk4_integrator_constructor - integration/rk4/src/rk4_second_order_ode_integrator - integration/rk4/src/rk4_second_order_ode_integrator_base - integration/rkf45/src/rkf45_butcher_tableau - integration/rkf45/src/rkf45_first_order_ode_integrator - integration/rkf45/src/rkf45_integrator_constructor - integration/rkf45/src/rkf45_second_order_ode_integrator - integration/rkf78/src/rkf78_butcher_tableau - integration/rkf78/src/rkf78_first_order_ode_integrator - integration/rkf78/src/rkf78_integrator_constructor - integration/rkf78/src/rkf78_second_order_ode_integrator - integration/rkg4/src/rkg4_butcher_tableau - integration/rkg4/src/rkg4_first_order_ode_integrator - integration/rkg4/src/rkg4_integrator_constructor - integration/rkg4/src/rkg4_second_order_ode_integrator - integration/rkn4/src/rkn4_integrator_constructor - integration/rkn4/src/rkn4_second_order_ode_integrator - integration/symplectic_euler/src/symplectic_euler_integrator_constructor - integration/symplectic_euler/src/symplectic_euler_second_order_ode_integrator - integration/velocity_verlet/src/velocity_verlet_integrator_constructor - integration/velocity_verlet/src/velocity_verlet_second_order_ode_integrator - interface/src/alloc - interface/src/deletable - interface/src/message_handler - math/src/n_choose_m - math/src/ratio128 - math/src/uint128 - trick/integration/src/trick_integrator + integration/abm4/src/abm4_first_order_ode_integrator.cc + integration/abm4/src/abm4_integrator_constructor.cc + integration/abm4/src/abm4_second_order_ode_integrator.cc + integration/beeman/src/beeman_integrator_constructor.cc + integration/beeman/src/beeman_second_order_ode_integrator.cc + integration/core/src/base_integration_group.cc + integration/core/src/bogus_integration_controls.cc + integration/core/src/first_order_ode_integrator.cc + integration/core/src/integration_controls.cc + integration/core/src/integration_messages.cc + integration/core/src/integrator_constructor.cc + integration/core/src/integrator_constructor_factory.cc + integration/core/src/integrator_result_merger.cc + integration/core/src/integrator_result_merger_container.cc + integration/core/src/left_quaternion_functions.cc + integration/core/src/priming_first_order_ode_integrator.cc + integration/core/src/priming_integration_controls.cc + integration/core/src/priming_integrator_constructor.cc + integration/core/src/priming_second_order_ode_integrator.cc + integration/core/src/second_order_ode_integrator.cc + integration/core/src/single_cycle_integration_controls.cc + integration/core/src/standard_integration_controls.cc + integration/euler/src/euler_first_order_ode_integrator.cc + integration/euler/src/euler_integrator_constructor.cc + integration/euler/src/euler_second_order_ode_integrator.cc + integration/mm4/src/mm4_integrator_constructor.cc + integration/mm4/src/mm4_second_order_ode_integrator.cc + integration/nl2/src/nl2_integrator_constructor.cc + integration/nl2/src/nl2_second_order_ode_integrator.cc + integration/position_verlet/src/position_verlet_integrator_constructor.cc + integration/position_verlet/src/position_verlet_second_order_ode_integrator.cc + integration/rk2_heun/src/rk2_heun_first_order_ode_integrator.cc + integration/rk2_heun/src/rk2_heun_integrator_constructor.cc + integration/rk2_heun/src/rk2_heun_second_order_ode_integrator.cc + integration/rk2_midpoint/src/rk2_midpoint_first_order_ode_integrator.cc + integration/rk2_midpoint/src/rk2_midpoint_integrator_constructor.cc + integration/rk2_midpoint/src/rk2_midpoint_second_order_ode_integrator.cc + integration/rk4/src/rk4_first_order_ode_integrator.cc + integration/rk4/src/rk4_integrator_constructor.cc + integration/rk4/src/rk4_second_order_ode_integrator.cc + integration/rk4/src/rk4_second_order_ode_integrator_base.cc + integration/rkf45/src/rkf45_butcher_tableau.cc + integration/rkf45/src/rkf45_first_order_ode_integrator.cc + integration/rkf45/src/rkf45_integrator_constructor.cc + integration/rkf45/src/rkf45_second_order_ode_integrator.cc + integration/rkf78/src/rkf78_butcher_tableau.cc + integration/rkf78/src/rkf78_first_order_ode_integrator.cc + integration/rkf78/src/rkf78_integrator_constructor.cc + integration/rkf78/src/rkf78_second_order_ode_integrator.cc + integration/rkg4/src/rkg4_butcher_tableau.cc + integration/rkg4/src/rkg4_first_order_ode_integrator.cc + integration/rkg4/src/rkg4_integrator_constructor.cc + integration/rkg4/src/rkg4_second_order_ode_integrator.cc + integration/rkn4/src/rkn4_integrator_constructor.cc + integration/rkn4/src/rkn4_second_order_ode_integrator.cc + integration/symplectic_euler/src/symplectic_euler_integrator_constructor.cc + integration/symplectic_euler/src/symplectic_euler_second_order_ode_integrator.cc + integration/velocity_verlet/src/velocity_verlet_integrator_constructor.cc + integration/velocity_verlet/src/velocity_verlet_second_order_ode_integrator.cc + interface/src/alloc.cc + interface/src/deletable.cc + interface/src/message_handler.cc + math/src/n_choose_m.cc + math/src/ratio128.cc + math/src/uint128.cc + trick/integration/src/trick_integrator.cc ) -add_library( er7_utils_objs OBJECT ${ER7_UTILS_SRC} ) +add_library( er7_utils STATIC ${ER7_UTILS_SRC} ${ER7_IO_SOURCES} ) +target_link_libraries( er7_utils PUBLIC trick_build_flags ) +target_compile_options( er7_utils PRIVATE -Wno-unused-parameter ) +set_target_properties( er7_utils PROPERTIES ARCHIVE_OUTPUT_NAME er7_utils) +add_dependencies( er7_utils trick_io_src_gen ) diff --git a/trick_source/java/CMakeLists.txt b/trick_source/java/CMakeLists.txt index 997b621b5..923308092 100644 --- a/trick_source/java/CMakeLists.txt +++ b/trick_source/java/CMakeLists.txt @@ -1,176 +1,56 @@ +# Trick's Java GUIs (trickview, simcontrol, dp, sie, ...), ported from this +# directory's own Makefile (top-level Makefile:242-274) and this project's +# pom.xml, which already has a "cmake" Maven profile +# (cmaketrue) that +# redirects the build output directory to -DbuildDirectory, matching the +# stale 2019 CMakeLists.txt's invocation — salvaged from there, but as a +# real add_custom_command with dependency tracking instead of a +# hand-maintained ~150-file source DEPENDS list, which had already drifted +# from the source tree once (see the sim_services/trick_utils source-list +# note in the Phase 2 status writeup). +# +# TRICK_OFFLINE copies prebuilt jars from trick-offline/ instead of invoking +# mvn (top-level Makefile:245-272); mirrored here rather than deferring to +# `mvn -o` since offline mode's jars are pre-built releases, not merely a +# local Maven cache. -############################################################### -# Build Java -############################################################### +set(TRICK_JAVA_BUILD_DIR ${CMAKE_BINARY_DIR}/libexec/trick/java/build) +if(NOT TRICK_OFFLINE) + file(GLOB_RECURSE TRICK_JAVA_SOURCES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/java/*.java + ) -set(JAVA_JARS - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/MTV.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/TrickView.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/JXPlot.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/QP.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/DP.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/Sie.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/Dre.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/SimControl.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/SimSniffer.jar - ${CMAKE_BINARY_DIR}/libexec/trick/java/build/MM.jar -) - -add_custom_target(java ALL DEPENDS ${JAVA_JARS}) - -add_custom_command( - OUTPUT - ${JAVA_JARS} - COMMAND COMMAND - ${MAVEN_EXECUTABLE} -q package -Dcmake=true -DbuildDirectory=${CMAKE_BINARY_DIR}/libexec/trick/java/build - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS - src/main/java/trick/dre/DreApplication.java - src/main/java/trick/sniffer/SimulationSniffer.java - src/main/java/trick/sniffer/SimulationInformation.java - src/main/java/trick/sniffer/SimulationListener.java - src/main/java/trick/sniffer/SimSnifferApplication.java - src/main/java/trick/simcontrol/utils/SimControlActionController.java - src/main/java/trick/simcontrol/utils/SimState.java - src/main/java/trick/simcontrol/SimControlApplication.java - src/main/java/trick/test/Client.java - src/main/java/trick/tv/TVApplication.java - src/main/java/trick/tv/StripChart.java - src/main/java/trick/tv/TVVariableTree.java - src/main/java/trick/tv/StripChartManager.java - src/main/java/trick/tv/DoubleComboBox.java - src/main/java/trick/tv/TVBean.java - src/main/java/trick/tv/TVDouble.java - src/main/java/trick/tv/TVInteger.java - src/main/java/trick/tv/TrickViewFluent.java - src/main/java/trick/tv/VariableTable.java - src/main/java/trick/tv/TVLong.java - src/main/java/trick/tv/TVEnumeration.java - src/main/java/trick/tv/TVShort.java - src/main/java/trick/tv/TVByte.java - src/main/java/trick/tv/TVBoolean.java - src/main/java/trick/tv/TVString.java - src/main/java/trick/tv/TVFloat.java - src/main/java/trick/common/ui/panels/ConnectionStatusBar.java - src/main/java/trick/common/ui/panels/FindBar.java - src/main/java/trick/common/ui/panels/SmallTrickIconLabel.java - src/main/java/trick/common/ui/panels/AnimationPlayer.java - src/main/java/trick/common/ui/panels/DataPanel.java - src/main/java/trick/common/ui/panels/ListPanel.java - src/main/java/trick/common/ui/panels/DynamicTree.java - src/main/java/trick/common/ui/UIUtils.java - src/main/java/trick/common/ui/components/DoubleJSlider.java - src/main/java/trick/common/ui/components/NumberTextField.java - src/main/java/trick/common/ui/components/CommonTreeNode.java - src/main/java/trick/common/ui/components/FontChooser.java - src/main/java/trick/common/ui/TrickFileFilter.java - src/main/java/trick/common/utils/vs/VSFloat.java - src/main/java/trick/common/utils/vs/VariableListener.java - src/main/java/trick/common/utils/vs/VSShort.java - src/main/java/trick/common/utils/vs/VSString.java - src/main/java/trick/common/utils/vs/VariableTracker.java - src/main/java/trick/common/utils/vs/VSBoolean.java - src/main/java/trick/common/utils/vs/Variable.java - src/main/java/trick/common/utils/vs/VariableServerFluent.java - src/main/java/trick/common/utils/vs/VSDouble.java - src/main/java/trick/common/utils/vs/VSInteger.java - src/main/java/trick/common/utils/vs/VSValue.java - src/main/java/trick/common/utils/vs/VSLong.java - src/main/java/trick/common/utils/vs/VSByte.java - src/main/java/trick/common/utils/SortedListModel.java - src/main/java/trick/common/utils/UnitType.java - src/main/java/trick/common/utils/DataReader.java - src/main/java/trick/common/utils/XMLCreator.java - src/main/java/trick/common/utils/ErrorChecker.java - src/main/java/trick/common/utils/UnitInfixExpression.java - src/main/java/trick/common/utils/CSVDataReader.java - src/main/java/trick/common/utils/LogVar.java - src/main/java/trick/common/utils/VariableServerConnection.java - src/main/java/trick/common/utils/BinaryDataReader.java - src/main/java/trick/common/utils/LogHeaderReader.java - src/main/java/trick/common/utils/TrickColors.java - src/main/java/trick/common/TrickApplication.java - src/main/java/trick/common/RunTimeTrickApplication.java - src/main/java/trick/vc/VariableCounter.java - src/main/java/trick/dataproducts/plot/JXPlotApplication.java - src/main/java/trick/dataproducts/plot/utils/TrickChart.java - src/main/java/trick/dataproducts/plot/utils/TrickChartControlPanel.java - src/main/java/trick/dataproducts/plot/utils/TrickXYPlot.java - src/main/java/trick/dataproducts/plot/utils/TrickChartFrame.java - src/main/java/trick/dataproducts/plot/utils/TrickXYSeries.java - src/main/java/trick/dataproducts/plot/utils/PlotUtils.java - src/main/java/trick/dataproducts/plot/utils/TrickChartPanel.java - src/main/java/trick/dataproducts/plot/utils/TrickChartTheme.java - src/main/java/trick/dataproducts/plot/utils/TrickFrame.java - src/main/java/trick/dataproducts/plot/utils/TrickXYLineAndShapeRenderer.java - src/main/java/trick/dataproducts/plot/utils/editor/DefaultLogAxisEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickTitleEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickNumberAxisEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickChartEditorManager.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickChartEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickPolarPlotEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickPlotEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickChartEditorFactory.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickValueAxisEditor.java - src/main/java/trick/dataproducts/plot/utils/editor/TrickAxisEditor.java - src/main/java/trick/dataproducts/plot/utils/TrickTableFrame.java - src/main/java/trick/dataproducts/utils/FileTreeNode.java - src/main/java/trick/dataproducts/utils/SessionRunTransferHandler.java - src/main/java/trick/dataproducts/utils/SessionXMLCreator.java - src/main/java/trick/dataproducts/utils/SessionRun.java - src/main/java/trick/dataproducts/utils/SimRunTree.java - src/main/java/trick/dataproducts/utils/SimDPTree.java - src/main/java/trick/dataproducts/utils/Session.java - src/main/java/trick/dataproducts/utils/SimRunDPTree.java - src/main/java/trick/dataproducts/utils/SessionDomParser.java - src/main/java/trick/dataproducts/utils/FileTreePanel.java - src/main/java/trick/dataproducts/trickqp/TrickQPApplication.java - src/main/java/trick/dataproducts/trickqp/utils/ProductTable.java - src/main/java/trick/dataproducts/trickqp/utils/TrickQPActionController.java - src/main/java/trick/dataproducts/trickqp/utils/ProductDataPanel.java - src/main/java/trick/dataproducts/trickqp/utils/QPRemoteCallInterface.java - src/main/java/trick/dataproducts/trickqp/utils/ProductVar.java - src/main/java/trick/dataproducts/trickqp/utils/ProductVarcase.java - src/main/java/trick/dataproducts/trickqp/utils/ProductMeasurement.java - src/main/java/trick/dataproducts/trickqp/utils/Product.java - src/main/java/trick/dataproducts/trickqp/utils/ProductColumn.java - src/main/java/trick/dataproducts/trickqp/utils/ProductPlot.java - src/main/java/trick/dataproducts/trickqp/utils/DataTransferHandler.java - src/main/java/trick/dataproducts/trickqp/utils/ProductCurve.java - src/main/java/trick/dataproducts/trickqp/utils/ProductPage.java - src/main/java/trick/dataproducts/trickqp/utils/ProductTree.java - src/main/java/trick/dataproducts/trickqp/utils/CommonProduct.java - src/main/java/trick/dataproducts/trickqp/utils/ProductExternalFunction.java - src/main/java/trick/dataproducts/trickqp/utils/QPRemoteCallInterfaceImpl.java - src/main/java/trick/dataproducts/trickqp/utils/ProductXMLCreator.java - src/main/java/trick/dataproducts/trickqp/utils/ProductDomParser.java - src/main/java/trick/dataproducts/trickqp/utils/ProductAxis.java - src/main/java/trick/dataproducts/trickqp/utils/VarListPanel.java - src/main/java/trick/dataproducts/DataProductsApplication.java - src/main/java/trick/dataproducts/trickdp/TrickDPApplication.java - src/main/java/trick/dataproducts/trickdp/utils/DPRemoteCallInterfaceImpl.java - src/main/java/trick/dataproducts/trickdp/utils/DPRemoteCallInterface.java - src/main/java/trick/dataproducts/trickdp/utils/TrickDPActionController.java - src/main/java/trick/dataproducts/trickdp/utils/PDFBooklet.java - src/main/java/trick/Template.java - src/main/java/trick/sie/utils/TreeModelExclusionFilter.java - src/main/java/trick/sie/utils/TreeModelSortingFilter.java - src/main/java/trick/sie/utils/SearchListener.java - src/main/java/trick/sie/utils/SieEnumeration.java - src/main/java/trick/sie/utils/VariableList.java - src/main/java/trick/sie/utils/Searcher.java - src/main/java/trick/sie/utils/SearchPanel.java - src/main/java/trick/sie/utils/SieTree.java - src/main/java/trick/sie/utils/SieTemplate.java - src/main/java/trick/sie/utils/SieVariableTree.java - src/main/java/trick/sie/utils/SieTreeModel.java - src/main/java/trick/sie/utils/TreeModelFilter.java - src/main/java/trick/sie/utils/SieResourceDomParser.java - src/main/java/trick/sie/SieApplication.java - src/main/java/trick/montemonitor/Slave.java - src/main/java/trick/montemonitor/MonteMonitorApplication.java - src/main/java/trick/mtv/MtvApp.java - src/main/java/trick/mtv/MtvView.java -) - + add_custom_command( + OUTPUT ${TRICK_JAVA_BUILD_DIR}/.stamp + COMMAND ${MVN_EXECUTABLE} -q package -Dcmake=true + -DbuildDirectory=${TRICK_JAVA_BUILD_DIR} + -Dmaven.wagon.http.retryHandler.count=15 + COMMAND ${CMAKE_COMMAND} -E touch ${TRICK_JAVA_BUILD_DIR}/.stamp + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${TRICK_JAVA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml + COMMENT "Building Trick Java GUIs (mvn package)" + VERBATIM + ) + add_custom_target(trick-java ALL DEPENDS ${TRICK_JAVA_BUILD_DIR}/.stamp) +else() + set(TRICK_JAVA_OFFLINE_JARS + DP Dre JXPlot MM MTV QP Sie SimControl SimSniffer TrickView + trick-java-${TRICK_MAJOR}.${TRICK_MINOR}.${TRICK_TINY} + ) + set(TRICK_JAVA_OFFLINE_TARGETS "") + foreach(_tr_jar ${TRICK_JAVA_OFFLINE_JARS}) + set(_tr_src ${CMAKE_SOURCE_DIR}/trick-offline/${_tr_jar}.jar) + set(_tr_dst ${TRICK_JAVA_BUILD_DIR}/${_tr_jar}.jar) + add_custom_command( + OUTPUT ${_tr_dst} + COMMAND ${CMAKE_COMMAND} -E make_directory ${TRICK_JAVA_BUILD_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${_tr_src} ${_tr_dst} + DEPENDS ${_tr_src} + COMMENT "Copying offline jar ${_tr_jar}.jar" + VERBATIM + ) + list(APPEND TRICK_JAVA_OFFLINE_TARGETS ${_tr_dst}) + endforeach() + add_custom_target(trick-java ALL DEPENDS ${TRICK_JAVA_OFFLINE_TARGETS}) +endif() diff --git a/trick_source/sim_services/CMakeLists.txt b/trick_source/sim_services/CMakeLists.txt index ff7eed9e3..c6ef9e58e 100644 --- a/trick_source/sim_services/CMakeLists.txt +++ b/trick_source/sim_services/CMakeLists.txt @@ -1,246 +1,276 @@ - -# Sim services C/C++ files +# Sim services C/C++ sources for libtrick.a (top Makefile's SIM_SERV_DIRS +# minus MemoryManager (own archive, liber7_utils split) and InputProcessor +# (goes into libtrick_pyip.a instead) — see A3. List derived by cross +# referencing every non-io_/class_map member of a real `make` build's +# lib/libtrick.a against the source tree (verified 2026-07-06); do not trust +# the 2019 stale CMakeLists.txt list, it predates several renames/additions +# (VariableServerSessionThread -> VariableServerSession, MonteCarloGeneration, +# JSONVariableServerThread, MessageCustomManager, ThreadBase/SysThread). set( SS_SRC - CheckPointAgent/CheckPointAgent - CheckPointAgent/ChkPtParseContext - CheckPointAgent/ClassicCheckPointAgent - CheckPointAgent/PythonPrint - CheckPointRestart/CheckPointRestart - CheckPointRestart/CheckPointRestart_c_intf - CheckPointRestart/next_attr_name - CheckPointRestart/stl_type_name_convert - Clock/BC635Clock - Clock/Clock - Clock/GetTimeOfDayClock - Clock/TPROCTEClock - Clock/clock_c_intf - Collect/collect - CommandLineArguments/CommandLineArguments - CommandLineArguments/command_line_c_intf - DataRecord/DRAscii - DataRecord/DRBinary - DataRecord/DRHDF5 - DataRecord/DataRecordDispatcher - DataRecord/DataRecordGroup - DataRecord/data_record_utilities - DebugPause/DebugPause - DebugPause/DebugPause_c_intf - EchoJobs/EchoJobs - EchoJobs/EchoJobs_c_intf - Environment/Environment - Environment/Environment_c_intf - EventManager/EventInstrument - EventManager/EventManager - EventManager/EventManager_c_intf - EventManager/EventProcessor - Executive/Executive - Executive/ExecutiveException - Executive/Executive_add_depends_on_job - Executive/Executive_add_jobs_to_queue - Executive/Executive_add_scheduled_job_class - Executive/Executive_add_sim_object - Executive/Executive_advance_sim_time - Executive/Executive_c_intf - Executive/Executive_call_default_data - Executive/Executive_call_initialization - Executive/Executive_call_input_processor - Executive/Executive_check_all_job_cycle_times - Executive/Executive_check_all_jobs_handled - Executive/Executive_checkpoint - Executive/Executive_clear_scheduled_queues - Executive/Executive_create_threads - Executive/Executive_fpe_handler - Executive/Executive_freeze - Executive/Executive_freeze_loop - Executive/Executive_get_curr_job - Executive/Executive_get_job - Executive/Executive_get_job_cycle - Executive/Executive_get_process_id - Executive/Executive_get_sim_time - Executive/Executive_init - Executive/Executive_init_freeze_scheduled - Executive/Executive_init_signal_handlers - Executive/Executive_instrument_job - Executive/Executive_isThreadReadyToRun - Executive/Executive_loop - Executive/Executive_loop_multi_thread - Executive/Executive_loop_single_thread - Executive/Executive_post_checkpoint - Executive/Executive_process_sim_args - Executive/Executive_register_scheduler - Executive/Executive_remove_jobs - Executive/Executive_remove_sim_object - Executive/Executive_restart - Executive/Executive_run - Executive/Executive_scheduled_thread_sync - Executive/Executive_set_job_cycle - Executive/Executive_set_job_onoff - Executive/Executive_set_simobject_onoff - Executive/Executive_set_thread_amf_cycle_time - Executive/Executive_set_thread_async_wait - Executive/Executive_set_thread_cpu_affinity - Executive/Executive_set_thread_enabled - Executive/Executive_set_thread_priority - Executive/Executive_set_thread_process_type - Executive/Executive_set_thread_rt_semaphore - Executive/Executive_set_time_tic_value - Executive/Executive_shutdown - Executive/Executive_signal_handler - Executive/Executive_stop - Executive/Executive_terminate - Executive/Executive_thread_sync - Executive/Executive_write_s_job_execution - Executive/Executive_write_s_run_summary - Executive/ThreadTrigger - Executive/Threads - Executive/Threads_child - Executive/Threads_set_amf_cycle_tics - Executive/Threads_set_async_wait - Executive/Threads_set_process_type - Executive/child_handler - Executive/fpe_handler - Executive/sig_hand - ExternalApplications/ExternalApplication - ExternalApplications/ExternalApplicationManager - ExternalApplications/ExternalApplication_c_intf - ExternalApplications/MalfunctionsTrickView - ExternalApplications/MonteMonitor - ExternalApplications/SimControlPanel - ExternalApplications/StripChart - ExternalApplications/TrickView - FrameLog/FrameDataRecordGroup - FrameLog/FrameLog - FrameLog/FrameLog_c_intf - Integrator/src/IntegLoopManager - Integrator/src/IntegLoopScheduler - Integrator/src/IntegLoopSimObject - Integrator/src/MultiDtIntegLoopScheduler - Integrator/src/MultiDtIntegLoopSimObject - Integrator/src/Integrator - Integrator/src/Integrator_C_Intf - Integrator/src/getIntegrator - Integrator/src/regula_falsi - Integrator/src/reset_regula_falsi - JITInputFile/JITEvent - JITInputFile/JITInputFile - JITInputFile/jit_input_file_c_intf - JSONVariableServer/JSONVariableServer - JSONVariableServer/JSONVariableServerSessionThread - MasterSlave/MSSharedMem - MasterSlave/MSSocket - MasterSlave/Master - MasterSlave/Slave - Message/MessageCout - Message/MessageFile - Message/MessageHSFile - Message/MessageCustomFile - Message/MessageLCout - Message/MessagePublisher - Message/MessageSubscriber - Message/MessageTCDevice - Message/MessageThreadedCout - Message/Message_c_intf - Message/PlaybackFile - Message/message_publish_standalone - MonteCarlo/MonteCarlo - MonteCarlo/MonteCarlo_c_intf - MonteCarlo/MonteCarlo_dispatch_run_to_slave - MonteCarlo/MonteCarlo_dryrun - MonteCarlo/MonteCarlo_execute_monte - MonteCarlo/MonteCarlo_funcs - MonteCarlo/MonteCarlo_initialize_sockets - MonteCarlo/MonteCarlo_master - MonteCarlo/MonteCarlo_master_file_io - MonteCarlo/MonteCarlo_master_init - MonteCarlo/MonteCarlo_master_shutdown - MonteCarlo/MonteCarlo_receive_results - MonteCarlo/MonteCarlo_run_queue - MonteCarlo/MonteCarlo_slave - MonteCarlo/MonteCarlo_slave_funcs - MonteCarlo/MonteCarlo_slave_init - MonteCarlo/MonteCarlo_slave_process_run - MonteCarlo/MonteCarlo_spawn_slaves - MonteCarlo/MonteVarCalculated - MonteCarlo/MonteVarFile - MonteCarlo/MonteVarFixed - MonteCarlo/MonteVarRandom - MonteCarlo/StlRandomGenerator - RealtimeInjector/RtiEvent - RealtimeInjector/RtiExec - RealtimeInjector/RtiList - RealtimeInjector/RtiStager - RealtimeSync/RealtimeSync - RealtimeSync/RealtimeSync_c_intf - ScheduledJobQueue/ScheduledJobQueue - ScheduledJobQueue/ScheduledJobQueueInstrument - Scheduler/Scheduler - Sie/AttributesMap - Sie/EnumAttributesMap - Sie/Sie - Sie/sie_c_intf - SimObject/JobData - SimObject/SimObject - SimTime/SimTime - SimTime/SimTime_c_intf - ThreadBase/ThreadBase - Timer/ITimer - Timer/Timer - Timer/it_handler - UdUnits/UdUnits - UdUnits/map_trick_units_to_udunits - UnitTest/UnitTest - UnitTest/UnitTest_c_intf - UnitsMap/UnitsMap - VariableServer/VariableReference - VariableServer/VariableServer - VariableServer/VariableServerListenThread - VariableServer/VariableServerSessionThread - VariableServer/VariableServerSessionThread_commands - VariableServer/VariableServerSessionThread_connect - VariableServer/VariableServerSessionThread_copy_data - VariableServer/VariableServerSessionThread_copy_sim_data - VariableServer/VariableServerSessionThread_create_socket - VariableServer/VariableServerSessionThread_freeze_init - VariableServer/VariableServerSessionThread_loop - VariableServer/VariableServerSessionThread_restart - VariableServer/VariableServerSessionThread_write_data - VariableServer/VariableServerSessionThread_write_stdio - VariableServer/VariableServer_copy_and_write_freeze - VariableServer/VariableServer_copy_and_write_freeze_scheduled - VariableServer/VariableServer_copy_and_write_scheduled - VariableServer/VariableServer_copy_and_write_top - VariableServer/VariableServer_default_data - VariableServer/VariableServer_freeze_init - VariableServer/VariableServer_get_next_freeze_call_time - VariableServer/VariableServer_get_next_sync_call_time - VariableServer/VariableServer_open_additional_servers - VariableServer/VariableServer_init - VariableServer/VariableServer_restart - VariableServer/VariableServer_shutdown - VariableServer/exit_var_thread - VariableServer/var_server_ext - Zeroconf/Zeroconf - mains/master + CheckPointAgent/CheckPointAgent.cpp + CheckPointAgent/ChkPtParseContext.cpp + CheckPointAgent/ClassicCheckPointAgent.cpp + CheckPointAgent/PythonPrint.cpp + CheckPointRestart/CheckPointRestart.cpp + CheckPointRestart/CheckPointRestart_c_intf.cpp + CheckPointRestart/next_attr_name.cpp + CheckPointRestart/stl_type_name_convert.cpp + Clock/Clock.cpp + Clock/GetTimeOfDayClock.cpp + Clock/clock_c_intf.cpp + Collect/collect.cpp + CommandLineArguments/CommandLineArguments.cpp + CommandLineArguments/command_line_c_intf.cpp + DataRecord/DRAscii.cpp + DataRecord/DRBinary.cpp + DataRecord/DRHDF5.cpp + DataRecord/DataRecordDispatcher.cpp + DataRecord/DataRecordGroup.cpp + DataRecord/data_record_utilities.cpp + DebugPause/DebugPause.cpp + DebugPause/DebugPause_c_intf.cpp + EchoJobs/EchoJobs.cpp + EchoJobs/EchoJobs_c_intf.cpp + Environment/Environment.cpp + Environment/Environment_c_intf.cpp + EventManager/EventInstrument.cpp + EventManager/EventManager.cpp + EventManager/EventManager_c_intf.cpp + EventManager/EventProcessor.cpp + Executive/Executive.cpp + Executive/ExecutiveException.cpp + Executive/Executive_add_depends_on_job.cpp + Executive/Executive_add_jobs_to_queue.cpp + Executive/Executive_add_scheduled_job_class.cpp + Executive/Executive_add_sim_object.cpp + Executive/Executive_advance_sim_time.cpp + Executive/Executive_c_intf.cpp + Executive/Executive_call_default_data.cpp + Executive/Executive_call_initialization.cpp + Executive/Executive_call_input_processor.cpp + Executive/Executive_check_all_job_cycle_times.cpp + Executive/Executive_check_all_jobs_handled.cpp + Executive/Executive_checkpoint.cpp + Executive/Executive_clear_scheduled_queues.cpp + Executive/Executive_create_threads.cpp + Executive/Executive_fpe_handler.cpp + Executive/Executive_freeze.cpp + Executive/Executive_freeze_loop.cpp + Executive/Executive_get_curr_job.cpp + Executive/Executive_get_job.cpp + Executive/Executive_get_job_cycle.cpp + Executive/Executive_get_process_id.cpp + Executive/Executive_get_sim_time.cpp + Executive/Executive_init.cpp + Executive/Executive_init_freeze_scheduled.cpp + Executive/Executive_init_signal_handlers.cpp + Executive/Executive_instrument_job.cpp + Executive/Executive_isThreadReadyToRun.cpp + Executive/Executive_loop.cpp + Executive/Executive_loop_multi_thread.cpp + Executive/Executive_loop_single_thread.cpp + Executive/Executive_post_checkpoint.cpp + Executive/Executive_process_sim_args.cpp + Executive/Executive_register_scheduler.cpp + Executive/Executive_remove_jobs.cpp + Executive/Executive_remove_sim_object.cpp + Executive/Executive_restart.cpp + Executive/Executive_run.cpp + Executive/Executive_scheduled_thread_sync.cpp + Executive/Executive_set_job_cycle.cpp + Executive/Executive_set_job_onoff.cpp + Executive/Executive_set_simobject_onoff.cpp + Executive/Executive_set_thread_amf_cycle_time.cpp + Executive/Executive_set_thread_async_wait.cpp + Executive/Executive_set_thread_cpu_affinity.cpp + Executive/Executive_set_thread_enabled.cpp + Executive/Executive_set_thread_priority.cpp + Executive/Executive_set_thread_process_type.cpp + Executive/Executive_set_thread_rt_semaphore.cpp + Executive/Executive_set_time_tic_value.cpp + Executive/Executive_shutdown.cpp + Executive/Executive_signal_handler.cpp + Executive/Executive_stop.cpp + Executive/Executive_terminate.cpp + Executive/Executive_thread_sync.cpp + Executive/Executive_write_s_job_execution.cpp + Executive/Executive_write_s_run_summary.cpp + Executive/ThreadTrigger.cpp + Executive/Threads.cpp + Executive/Threads_child.cpp + Executive/Threads_set_amf_cycle_tics.cpp + Executive/Threads_set_async_wait.cpp + Executive/Threads_set_process_type.cpp + Executive/child_handler.cpp + Executive/fpe_handler.cpp + Executive/sig_hand.cpp + ExternalApplications/ExternalApplication.cpp + ExternalApplications/ExternalApplicationManager.cpp + ExternalApplications/ExternalApplication_c_intf.cpp + ExternalApplications/MalfunctionsTrickView.cpp + ExternalApplications/MonteMonitor.cpp + ExternalApplications/SimControlPanel.cpp + ExternalApplications/StripChart.cpp + ExternalApplications/TrickView.cpp + FrameLog/FrameDataRecordGroup.cpp + FrameLog/FrameLog.cpp + FrameLog/FrameLog_c_intf.cpp + Integrator/src/IntegLoopManager.cpp + Integrator/src/IntegLoopScheduler.cpp + Integrator/src/IntegLoopSimObject.cpp + Integrator/src/Integrator.cpp + Integrator/src/Integrator_C_Intf.cpp + Integrator/src/MultiDtIntegLoopScheduler.cpp + Integrator/src/MultiDtIntegLoopSimObject.cpp + Integrator/src/getIntegrator.cpp + Integrator/src/regula_falsi.c + Integrator/src/reset_regula_falsi.c + JITInputFile/JITEvent.cpp + JITInputFile/JITInputFile.cpp + JITInputFile/jit_input_file_c_intf.cpp + JSONVariableServer/JSONVariableServer.cpp + JSONVariableServer/JSONVariableServerThread.cpp + MasterSlave/MSSharedMem.cpp + MasterSlave/MSSocket.cpp + MasterSlave/Master.cpp + MasterSlave/Slave.cpp + Message/MessageCout.cpp + Message/MessageCustomFile.cpp + Message/MessageCustomManager.cpp + Message/MessageFile.cpp + Message/MessageHSFile.cpp + Message/MessageLCout.cpp + Message/MessagePublisher.cpp + Message/MessageSubscriber.cpp + Message/MessageTCDevice.cpp + Message/MessageThreadedCout.cpp + Message/Message_c_intf.cpp + Message/PlaybackFile.cpp + Message/message_publish_standalone.cpp + MonteCarlo/MonteCarlo.cpp + MonteCarlo/MonteCarlo_c_intf.cpp + MonteCarlo/MonteCarlo_dispatch_run_to_slave.cpp + MonteCarlo/MonteCarlo_dryrun.cpp + MonteCarlo/MonteCarlo_execute_monte.cpp + MonteCarlo/MonteCarlo_funcs.cpp + MonteCarlo/MonteCarlo_initialize_sockets.cpp + MonteCarlo/MonteCarlo_master.cpp + MonteCarlo/MonteCarlo_master_file_io.cpp + MonteCarlo/MonteCarlo_master_init.cpp + MonteCarlo/MonteCarlo_master_shutdown.cpp + MonteCarlo/MonteCarlo_receive_results.cpp + MonteCarlo/MonteCarlo_run_queue.cpp + MonteCarlo/MonteCarlo_slave.cpp + MonteCarlo/MonteCarlo_slave_funcs.cpp + MonteCarlo/MonteCarlo_slave_init.cpp + MonteCarlo/MonteCarlo_slave_process_run.cpp + MonteCarlo/MonteCarlo_spawn_slaves.cpp + MonteCarlo/MonteVarCalculated.cpp + MonteCarlo/MonteVarFile.cpp + MonteCarlo/MonteVarFixed.cpp + MonteCarlo/MonteVarRandom.cpp + MonteCarlo/StlRandomGenerator.cpp + MonteCarloGeneration/mc_master.cc + MonteCarloGeneration/mc_variable.cc + MonteCarloGeneration/mc_variable_file.cc + MonteCarloGeneration/mc_variable_random_normal.cc + MonteCarloGeneration/mc_variable_random_string.cc + MonteCarloGeneration/mc_variable_random_uniform.cc + RealtimeInjector/RtiEvent.cpp + RealtimeInjector/RtiExec.cpp + RealtimeInjector/RtiList.cpp + RealtimeInjector/RtiStager.cpp + RealtimeSync/RealtimeSync.cpp + RealtimeSync/RealtimeSync_c_intf.cpp + ScheduledJobQueue/ScheduledJobQueue.cpp + ScheduledJobQueue/ScheduledJobQueueInstrument.cpp + Scheduler/Scheduler.cpp + Sie/AttributesMap.cpp + Sie/EnumAttributesMap.cpp + Sie/Sie.cpp + Sie/sie_c_intf.cpp + SimObject/JobData.cpp + SimObject/SimObject.cpp + SimTime/SimTime.cpp + SimTime/SimTime_c_intf.cpp + ThreadBase/SysThread.cpp + ThreadBase/ThreadBase.cpp + Timer/ITimer.cpp + Timer/Timer.cpp + Timer/it_handler.cpp + UdUnits/UdUnits.cpp + UdUnits/map_trick_units_to_udunits.cpp + UnitTest/UnitTest.cpp + UnitTest/UnitTest_c_intf.cpp + UnitsMap/UnitsMap.cpp + VariableServer/VariableReference.cpp + VariableServer/VariableServer.cpp + VariableServer/VariableServerListenThread.cpp + VariableServer/VariableServerSession.cpp + VariableServer/VariableServerSessionThread.cpp + VariableServer/VariableServerSessionThread_loop.cpp + VariableServer/VariableServerSession_commands.cpp + VariableServer/VariableServerSession_copy_and_write_modes.cpp + VariableServer/VariableServerSession_copy_sim_data.cpp + VariableServer/VariableServerSession_freeze_init.cpp + VariableServer/VariableServerSession_write_data.cpp + VariableServer/VariableServerSession_write_stdio.cpp + VariableServer/VariableServer_copy_and_write_freeze.cpp + VariableServer/VariableServer_copy_and_write_freeze_scheduled.cpp + VariableServer/VariableServer_copy_and_write_scheduled.cpp + VariableServer/VariableServer_copy_and_write_top.cpp + VariableServer/VariableServer_default_data.cpp + VariableServer/VariableServer_freeze_init.cpp + VariableServer/VariableServer_get_next_freeze_call_time.cpp + VariableServer/VariableServer_get_next_sync_call_time.cpp + VariableServer/VariableServer_init.cpp + VariableServer/VariableServer_open_additional_servers.cpp + VariableServer/VariableServer_restart.cpp + VariableServer/VariableServer_shutdown.cpp + VariableServer/exit_var_thread.cpp + VariableServer/var_server_ext.cpp + Zeroconf/Zeroconf.cpp + mains/master.cpp ) -# Sim services Lex/Yacc files -set( SS_LEX_YACC_SRC - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.lex - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.tab +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) +flex_target(trick_ss_input_lexer CheckPointAgent/input_parser.l ${CMAKE_CURRENT_BINARY_DIR}/input_parser.lex.cpp) +bison_target(trick_ss_input_parser CheckPointAgent/input_parser.y ${CMAKE_CURRENT_BINARY_DIR}/input_parser.tab.cpp) +set_source_files_properties(${FLEX_trick_ss_input_lexer_OUTPUTS} PROPERTIES + COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-unused-function;-Wno-sign-compare;-x;c++" ) - -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.lex.cpp - COMMAND ${FLEX_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.lex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CheckPointAgent/input_parser.l - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/CheckPointAgent/input_parser.l +set_source_files_properties(${BISON_trick_ss_input_parser_OUTPUTS} PROPERTIES + COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-unused;-x;c++" ) -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.tab.cpp ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.tab.hpp - COMMAND ${BISON_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/input_parser.tab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CheckPointAgent/input_parser.y - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/CheckPointAgent/input_parser.y +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set_property(SOURCE ${BISON_trick_ss_input_parser_OUTPUTS} APPEND PROPERTY + COMPILE_OPTIONS "-Wno-parentheses-equality") +endif() + +add_library( sim_services_objs OBJECT + ${SS_SRC} + ${FLEX_trick_ss_input_lexer_OUTPUTS} + ${BISON_trick_ss_input_parser_OUTPUTS} ) +target_link_libraries( sim_services_objs PUBLIC trick_build_flags ) -add_library( sim_services_objs OBJECT ${SS_SRC} ${SS_LEX_YACC_SRC}) -target_include_directories( sim_services_objs PUBLIC ${PYTHON_INCLUDE_DIRS} ) -target_include_directories( sim_services_objs PUBLIC ${UDUNITS2_INCLUDES} ) +# HDF5 support in DataRecord/DRHDF5.cpp (Makefile: DataRecord/Makefile:6-9). +# Deliberately per-source rather than target_link_libraries(... trick::hdf5): +# source properties can't consume a target's usage requirements, and this +# object's -I scoping must match the Makefile's file-local override exactly. +if(HDF5_HOME) + set_property(SOURCE DataRecord/DRHDF5.cpp APPEND PROPERTY COMPILE_DEFINITIONS HDF5) + if(NOT HDF5_HOME STREQUAL "/usr") + set_property(SOURCE DataRecord/DRHDF5.cpp APPEND PROPERTY COMPILE_OPTIONS "-I${HDF5_HOME}/include") + endif() +endif() +# GSL support for MonteCarlo.cpp comes from trick_build_flags (root +# CMakeLists.txt), not a per-file override here: MonteCarlo/Makefile's own +# GSL block is gated on $(HAVE_GSL), a variable nothing in the config system +# ever sets — dead code. The _HAVE_GSL define MonteCarlo.cpp (and +# include/trick/rand_generator.h) actually see in the real build comes +# entirely from Makefile.common's global TRICK_SYSTEM_CXXFLAGS. add_subdirectory(MemoryManager) add_subdirectory(InputProcessor) diff --git a/trick_source/sim_services/Clock/test/.gitignore b/trick_source/sim_services/Clock/test/.gitignore index 7aadd5803..fd94e374a 100644 --- a/trick_source/sim_services/Clock/test/.gitignore +++ b/trick_source/sim_services/Clock/test/.gitignore @@ -1,4 +1,3 @@ -*.o BC635Clock_test TPROCTEClock_test GetTimeOfDayClock_test diff --git a/trick_source/sim_services/CommandLineArguments/test/.gitignore b/trick_source/sim_services/CommandLineArguments/test/.gitignore index c9567dcfc..a9083e3c0 100644 --- a/trick_source/sim_services/CommandLineArguments/test/.gitignore +++ b/trick_source/sim_services/CommandLineArguments/test/.gitignore @@ -1,3 +1,2 @@ create_path_test CommandLineArguments_test -*.o diff --git a/trick_source/sim_services/CommandLineArguments/test/Makefile b/trick_source/sim_services/CommandLineArguments/test/Makefile index d8fc2b26a..ed7498bac 100644 --- a/trick_source/sim_services/CommandLineArguments/test/Makefile +++ b/trick_source/sim_services/CommandLineArguments/test/Makefile @@ -14,8 +14,22 @@ TRICK_SYSTEM_CXXFLAGS := $(subst -isystem,-I,$(TRICK_SYSTEM_CXXFLAGS)) TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS} # so it seems like there's some weirdness linking in the bitfield objects since they are C -MM_OBJECTS = $(TRICK_HOME)/trick_source/sim_services/MemoryManager/object_${TRICK_HOST_CPU}/extract_bitfield.o \ - $(TRICK_HOME)/trick_source/sim_services/MemoryManager/object_${TRICK_HOST_CPU}/extract_unsigned_bitfield.o +# +# Extracted from libtrick_mm.a rather than read from MemoryManager's +# source-tree object_$(TRICK_HOST_CPU)/ dir: that path only exists after an +# in-source `make` build of Trick itself, but this test's own TRICK_HOME can +# also be an out-of-source CMake install (cmake/TrickTest.cmake overrides +# TRICK_HOME to the staged prefix, which only ships the archive, not +# per-object build artifacts). Extracting from the archive works under both +# build systems, and tolerates their differing object basenames +# (extract_bitfield.o vs extract_bitfield.c.o). +MM_OBJDIR = mm_bitfield_objs +MM_OBJECTS = $(MM_OBJDIR)/.extracted + +$(MM_OBJDIR)/.extracted: ${TRICK_LIB_DIR}/libtrick_mm.a + mkdir -p $(MM_OBJDIR) + cd $(MM_OBJDIR) && ar x $(abspath $<) $$(ar t $(abspath $<) | grep -E '^extract_(unsigned_)?bitfield') + touch $@ #TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick -ltrick_pyip -ltrick_connection_handlers -ltrick_comm -ltrick_mm -ltrick_units -ltrick -ltrick_mm TRICK_LIB_NAMES = trick_mm trick_units trick trick_pyip trick_connection_handlers trick_comm @@ -44,13 +58,13 @@ test: $(TESTS) clean : rm -f $(TESTS) *.o *.gcno *.gcda - rm -rf a pre_existing_output_dir/a ../a + rm -rf a pre_existing_output_dir/a ../a $(MM_OBJDIR) create_path_test.o : create_path_test.cpp $(TRICK_CXX) $(TRICK_CXXFLAGS) -c $< create_path_test : create_path_test.o $(MM_OBJECTS) - $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ create_path_test.o $(MM_OBJDIR)/*.o -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) CommandLineArguments_test.o : CommandLineArguments_test.cpp $(TRICK_CXX) $(TRICK_CXXFLAGS) -c $< diff --git a/trick_source/sim_services/Executive/test/.gitignore b/trick_source/sim_services/Executive/test/.gitignore index c0eac510e..bb1bcd063 100644 --- a/trick_source/sim_services/Executive/test/.gitignore +++ b/trick_source/sim_services/Executive/test/.gitignore @@ -1,2 +1 @@ -*.o Executive_test diff --git a/trick_source/sim_services/InputProcessor/CMakeLists.txt b/trick_source/sim_services/InputProcessor/CMakeLists.txt index f4809b66c..ab6e5c146 100644 --- a/trick_source/sim_services/InputProcessor/CMakeLists.txt +++ b/trick_source/sim_services/InputProcessor/CMakeLists.txt @@ -1,13 +1,12 @@ - set( INPUT_PROCESSOR_SRC - IPPython - IPPythonEvent - InputProcessor - MTV - MTV_c_intf - input_processor_ext + IPPython.cpp + IPPythonEvent.cpp + InputProcessor.cpp + MTV.cpp + MTV_c_intf.cpp + input_processor_ext.cpp ) add_library( input_processor_objs OBJECT ${INPUT_PROCESSOR_SRC}) -target_include_directories( input_processor_objs PUBLIC ${PYTHON_INCLUDE_DIRS} ) - +target_link_libraries( input_processor_objs PUBLIC trick_build_flags ) +target_include_directories( input_processor_objs PRIVATE ${Python3_INCLUDE_DIRS} ) diff --git a/trick_source/sim_services/Integrator/test/.gitignore b/trick_source/sim_services/Integrator/test/.gitignore index 626aae794..05e5a9c18 100644 --- a/trick_source/sim_services/Integrator/test/.gitignore +++ b/trick_source/sim_services/Integrator/test/.gitignore @@ -1,2 +1 @@ -*.o Integrator_unittest diff --git a/trick_source/sim_services/Integrator/test/Makefile b/trick_source/sim_services/Integrator/test/Makefile index 0896036ff..976425475 100644 --- a/trick_source/sim_services/Integrator/test/Makefile +++ b/trick_source/sim_services/Integrator/test/Makefile @@ -25,23 +25,34 @@ TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtes # created to the list. TESTS = Integrator_unittest -OTHER_OBJECTS = \ - ../../include/object_${TRICK_HOST_CPU}/io_ABM_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_Euler_Cromer_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_Euler_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_MM4_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_NL2_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_RK2_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_RK4_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_RKF45_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_RKF78_Integrator.o \ - ../../include/object_${TRICK_HOST_CPU}/io_RKG4_Integrator.o - -OTHER_OBJECTS += \ -${TRICK_HOME}/trick_source/er7_utils/integration/*/object_${TRICK_HOST_CPU}/*.o \ -${TRICK_HOME}/trick_source/er7_utils/interface/object_${TRICK_HOST_CPU}/*.o \ -${TRICK_HOME}/trick_source/er7_utils/trick/integration/object_${TRICK_HOST_CPU}/*.o +# These force-include individual .o files rather than relying on -ltrick/ +# -ler7_utils archive linking: these are ICG-registration objects whose +# static initializers (type introspection) nothing in this test directly +# calls, so a normal `-lname` archive link — which only pulls in members +# that satisfy an unresolved symbol reference — silently drops them. +# +# Extracted from libtrick.a / liber7_utils.a instead of read from +# component-level object_$(TRICK_HOST_CPU)/ dirs: those source-tree paths +# only exist after an in-source `make` build, but this test's own +# TRICK_HOME can also be an out-of-source CMake install (same pattern/ +# rationale as CommandLineArguments/test/Makefile's MM_OBJECTS). All of +# liber7_utils.a's members originate from exactly the integration/*, +# interface/, and trick/integration/ subtrees this Makefile used to +# wildcard-glob directly, so extracting the whole archive reproduces that +# scope exactly. +INTEGRATOR_OBJDIR = integrator_objs +ER7_OBJDIR = er7_utils_objs +OTHER_OBJECTS = $(INTEGRATOR_OBJDIR)/.extracted $(ER7_OBJDIR)/.extracted + +$(INTEGRATOR_OBJDIR)/.extracted: ${TRICK_LIB_DIR}/libtrick.a + mkdir -p $(INTEGRATOR_OBJDIR) + cd $(INTEGRATOR_OBJDIR) && ar x $(abspath $<) $$(ar t $(abspath $<) | grep -E '^io_(ABM_Integrator|Euler_Cromer_Integrator|Euler_Integrator|Integrator|MM4_Integrator|NL2_Integrator|RK2_Integrator|RK4_Integrator|RKF45_Integrator|RKF78_Integrator|RKG4_Integrator)\.') + touch $@ + +$(ER7_OBJDIR)/.extracted: ${TRICK_LIB_DIR}/liber7_utils.a + mkdir -p $(ER7_OBJDIR) + cd $(ER7_OBJDIR) && ar x $(abspath $<) + touch $@ # House-keeping build targets. @@ -52,10 +63,10 @@ test: $(TESTS) clean : rm -f $(TESTS) *.o - rm -rf io_src xml + rm -rf io_src xml $(INTEGRATOR_OBJDIR) $(ER7_OBJDIR) Integrator_unittest.o : Integrator_unittest.cc $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< -Integrator_unittest : Integrator_unittest.o - $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ $(OTHER_OBJECTS) $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) +Integrator_unittest : Integrator_unittest.o $(OTHER_OBJECTS) + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ Integrator_unittest.o $(INTEGRATOR_OBJDIR)/*.o $(ER7_OBJDIR)/*.o $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) diff --git a/trick_source/sim_services/MemoryManager/CMakeLists.txt b/trick_source/sim_services/MemoryManager/CMakeLists.txt index 19903de0a..36b1c143a 100644 --- a/trick_source/sim_services/MemoryManager/CMakeLists.txt +++ b/trick_source/sim_services/MemoryManager/CMakeLists.txt @@ -1,81 +1,86 @@ set( TRICK_MM_SRC - ADefParseContext - MemoryManager - MemoryManager_C_Intf - MemoryManager_JSON_Intf - MemoryManager_add_attr_info - MemoryManager_add_checkpoint_alloc_dependency - MemoryManager_add_shared_library_symbols - MemoryManager_add_template_name_trans - MemoryManager_add_var - MemoryManager_alloc_depends - MemoryManager_alloc_info_map - MemoryManager_clear_memory - MemoryManager_declare_var - MemoryManager_delete_var - MemoryManager_get_enumerated - MemoryManager_get_size - MemoryManager_get_stl_dependencies - MemoryManager_get_type_attributes - MemoryManager_io_src_intf - MemoryManager_is_alloced - MemoryManager_make_declaration - MemoryManager_make_reference_attr - MemoryManager_map_external_object - MemoryManager_realloc - MemoryManager_ref_allocate - MemoryManager_ref_assignment - MemoryManager_ref_attributes - MemoryManager_ref_dim - MemoryManager_ref_name - MemoryManager_ref_name_from_address - MemoryManager_ref_var - MemoryManager_restore - MemoryManager_restore_stls - MemoryManager_set_checkpointagent - MemoryManager_set_debug_level - MemoryManager_strdup - MemoryManager_write_checkpoint - MemoryManager_write_var - RefParseContext - addr_bitfield - extract_bitfield - extract_unsigned_bitfield - follow_address_path - insert_bitfield - parameter_types - ref_free - ref_to_value - trickTypeCharString - vval - wcs_ext + ADefParseContext.cpp + AttributesUtils.cpp + MemoryManager.cpp + MemoryManager_C_Intf.cpp + MemoryManager_JSON_Intf.cpp + MemoryManager_add_attr_info.cpp + MemoryManager_add_checkpoint_alloc_dependency.cpp + MemoryManager_add_shared_library_symbols.cpp + MemoryManager_add_template_name_trans.cpp + MemoryManager_add_var.cpp + MemoryManager_alloc_depends.cpp + MemoryManager_alloc_info_map.cpp + MemoryManager_clear_memory.cpp + MemoryManager_declare_var.cpp + MemoryManager_delete_var.cpp + MemoryManager_get_attributes_for_address.cpp + MemoryManager_get_enumerated.cpp + MemoryManager_get_size.cpp + MemoryManager_get_stl_dependencies.cpp + MemoryManager_get_type_attributes.cpp + MemoryManager_io_src_intf.cpp + MemoryManager_is_alloced.cpp + MemoryManager_make_declaration.cpp + MemoryManager_make_reference_attr.cpp + MemoryManager_map_external_object.cpp + MemoryManager_realloc.cpp + MemoryManager_ref_allocate.cpp + MemoryManager_ref_assignment.cpp + MemoryManager_ref_attributes.cpp + MemoryManager_ref_dim.cpp + MemoryManager_ref_name.cpp + MemoryManager_ref_name_from_address.cpp + MemoryManager_ref_var.cpp + MemoryManager_restore.cpp + MemoryManager_restore_stls.cpp + MemoryManager_set_checkpointagent.cpp + MemoryManager_set_debug_level.cpp + MemoryManager_strdup.cpp + MemoryManager_write_checkpoint.cpp + MemoryManager_write_var.cpp + RefParseContext.cpp + addr_bitfield.c + extract_bitfield.c + extract_unsigned_bitfield.c + follow_address_path.c + insert_bitfield.c + ref_free.cpp + ref_to_value.c + trickTypeCharString.c + vval.c + wcs_ext.c ) -# Sim services Lex/Yacc files -set( MM_LEX_YACC_SRC - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.lex - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.tab - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.lex - ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.tab -) +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.lex.cpp - COMMAND ${FLEX_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.lex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/adef_parser.l - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/adef_parser.l -) -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.tab.cpp ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.tab.hpp - COMMAND ${BISON_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/adef_parser.tab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/adef_parser.y - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/adef_parser.y +flex_target(trick_mm_adef_lexer adef_parser.l ${CMAKE_CURRENT_BINARY_DIR}/adef_parser.lex.cpp) +bison_target(trick_mm_adef_parser adef_parser.y ${CMAKE_CURRENT_BINARY_DIR}/adef_parser.tab.cpp) +flex_target(trick_mm_ref_lexer ref_parser.l ${CMAKE_CURRENT_BINARY_DIR}/ref_parser.lex.cpp) +bison_target(trick_mm_ref_parser ref_parser.y ${CMAKE_CURRENT_BINARY_DIR}/ref_parser.tab.cpp) + +add_library( trick_mm STATIC + ${TRICK_MM_SRC} + ${FLEX_trick_mm_adef_lexer_OUTPUTS} + ${BISON_trick_mm_adef_parser_OUTPUTS} + ${FLEX_trick_mm_ref_lexer_OUTPUTS} + ${BISON_trick_mm_ref_parser_OUTPUTS} ) -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.lex.cpp - COMMAND ${FLEX_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.lex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ref_parser.l - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/ref_parser.l +target_link_libraries( trick_mm PUBLIC trick_build_flags ) +set_target_properties( trick_mm PROPERTIES ARCHIVE_OUTPUT_NAME trick_mm) + +# Match the Makefile's per-generator-output warning suppressions +# (CheckPointAgent/Makefile applies the same pattern; see A3). +set_source_files_properties( + ${FLEX_trick_mm_adef_lexer_OUTPUTS} ${FLEX_trick_mm_ref_lexer_OUTPUTS} + PROPERTIES COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-unused-function;-Wno-sign-compare;-x;c++" ) -add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.tab.cpp ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.tab.hpp - COMMAND ${BISON_EXECUTABLE} -d -o ${CMAKE_BINARY_DIR}/temp_src/lex_yacc/ref_parser.tab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ref_parser.y - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/ref_parser.y +set_source_files_properties( + ${BISON_trick_mm_adef_parser_OUTPUTS} ${BISON_trick_mm_ref_parser_OUTPUTS} + PROPERTIES COMPILE_OPTIONS "-Wno-unused-parameter;-Wno-unused;-x;c++" ) - -add_library( trick_mm STATIC ${TRICK_MM_SRC} ${MM_LEX_YACC_SRC}) -target_include_directories( trick_mm PUBLIC ${UDUNITS2_INCLUDES} ) - +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set_property(SOURCE ${BISON_trick_mm_adef_parser_OUTPUTS} ${BISON_trick_mm_ref_parser_OUTPUTS} + APPEND PROPERTY COMPILE_OPTIONS "-Wno-parentheses-equality") +endif() diff --git a/trick_source/sim_services/MemoryManager/test/.gitignore b/trick_source/sim_services/MemoryManager/test/.gitignore index 15d4e8c28..e0124f6a1 100644 --- a/trick_source/sim_services/MemoryManager/test/.gitignore +++ b/trick_source/sim_services/MemoryManager/test/.gitignore @@ -1,4 +1,3 @@ -*.o .icg_no_found Bitfield_tests MM_alloc_deps @@ -21,4 +20,4 @@ MM_write_checkpoint MM_write_checkpoint_hexfloat MM_write_var_unittest MM_stl_checkpoint -MM_stl_restore \ No newline at end of file +MM_stl_restore diff --git a/trick_source/sim_services/MonteCarlo/test/.gitignore b/trick_source/sim_services/MonteCarlo/test/.gitignore index 82c9a9536..a09776546 100644 --- a/trick_source/sim_services/MonteCarlo/test/.gitignore +++ b/trick_source/sim_services/MonteCarlo/test/.gitignore @@ -1,3 +1,2 @@ -*.o MonteCarlo_exceptions MonteCarlo_test diff --git a/trick_source/sim_services/ScheduledJobQueue/test/.gitignore b/trick_source/sim_services/ScheduledJobQueue/test/.gitignore index 098cdd8f1..961d083b6 100644 --- a/trick_source/sim_services/ScheduledJobQueue/test/.gitignore +++ b/trick_source/sim_services/ScheduledJobQueue/test/.gitignore @@ -1,2 +1 @@ -*.o ScheduledJobQueue_test diff --git a/trick_source/sim_services/Timer/test/.gitignore b/trick_source/sim_services/Timer/test/.gitignore index 611d4db12..7b45683f5 100644 --- a/trick_source/sim_services/Timer/test/.gitignore +++ b/trick_source/sim_services/Timer/test/.gitignore @@ -1,2 +1 @@ -*.o ITimer_test diff --git a/trick_source/sim_services/VariableServer/test/.gitignore b/trick_source/sim_services/VariableServer/test/.gitignore index ea339cfdc..9afd9297a 100644 --- a/trick_source/sim_services/VariableServer/test/.gitignore +++ b/trick_source/sim_services/VariableServer/test/.gitignore @@ -1,4 +1,3 @@ lcov_html/* -*.o *_test -*.info \ No newline at end of file +*.info diff --git a/trick_source/trick_swig/CMakeLists.txt b/trick_source/trick_swig/CMakeLists.txt new file mode 100644 index 000000000..f430baa22 --- /dev/null +++ b/trick_source/trick_swig/CMakeLists.txt @@ -0,0 +1,102 @@ +# libtrick_pyip.a: SWIG-generated Trick/Python interface code, ported from +# this directory's Makefile (the authority — see A3/A4). +# +# SWIG_EXECUTABLE/SWIG_VERSION come from cmake/TrickPrograms.cmake's own +# find_program(NAMES swig) — do NOT find_package(SWIG) here, it re-runs +# FindSWIG.cmake's own executable search and can override SWIG_EXECUTABLE +# with a version-suffixed binary (e.g. swig4.0), mismatching config_user.mk's +# SWIG value (see CMAKE_MIGRATION_PLAN.md Phase 1/2 CI parity fixes). +if(NOT SWIG_EXECUTABLE) + message(FATAL_ERROR "SWIG_EXECUTABLE not set — include(TrickPrograms) first") +endif() + +# D3: CMake writes nothing into the source tree — .py wrappers land in the +# build tree; Phase 3's `stage` install target is what assembles a runnable +# TRICK_HOME (including share/trick/swig/*.py) for sim-flow validation. +set(TRICK_SWIG_OUTDIR ${CMAKE_BINARY_DIR}/share/trick/swig) +file(MAKE_DIRECTORY ${TRICK_SWIG_OUTDIR}) + +set(_tr_swig_defs "") +if(HDF5_HOME) + list(APPEND _tr_swig_defs -DHDF5) +endif() +if(GSL_HOME) + list(APPEND _tr_swig_defs -D_HAVE_GSL) +endif() +if(TRICK_USE_ER7_UTILS) + list(APPEND _tr_swig_defs -DUSE_ER7_UTILS_INTEGRATORS) + if(EXISTS ${CMAKE_SOURCE_DIR}/trick_source/er7_utils/CheckpointHelper) + list(APPEND _tr_swig_defs -DUSE_ER7_UTILS_CHECKPOINTHELPER) + endif() +endif() +# Gate on USE_CIVETWEB (detection result), not the raw TRICK_CIVETWEB_HOME +# cache option — trick_swig/Makefile:57 gates SWIG_DEFS on +# `ifeq ($(USE_CIVETWEB), 1)`, which is also 1 when civetweb.h auto-detects +# at /usr with no --with-civetweb/TRICK_CIVETWEB_HOME given. +if(USE_CIVETWEB) + list(APPEND _tr_swig_defs -DUSE_CIVETWEB) +endif() + +function(trick_add_swig_wrap name) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_wrap.cpp + COMMAND ${SWIG_EXECUTABLE} ${_tr_swig_defs} + -I${CMAKE_SOURCE_DIR}/trick_source -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR} + -c++ -python -includeall -ignoremissing -w201,362,389,451 + -o ${CMAKE_CURRENT_BINARY_DIR}/${name}_wrap.cpp + -outdir ${TRICK_SWIG_OUTDIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${name}.i + MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${name}.i + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/extra_functions.i ${CMAKE_CURRENT_SOURCE_DIR}/units_attach.i + COMMENT "SWIG ${name}.i" + VERBATIM + ) +endfunction() + +trick_add_swig_wrap(sim_services) +trick_add_swig_wrap(swig_double) +trick_add_swig_wrap(swig_int) +trick_add_swig_wrap(swig_ref) + +add_library( trick_pyip STATIC + ${CMAKE_CURRENT_BINARY_DIR}/sim_services_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_double_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_int_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_ref_wrap.cpp + PrimitiveAttributesMap.cpp + swig_convert_units.cpp + swig_global_vars.cpp + $ +) +target_link_libraries( trick_pyip PUBLIC trick_build_flags ) +target_include_directories( trick_pyip PRIVATE ${Python3_INCLUDE_DIRS} ) +set_target_properties( trick_pyip PROPERTIES ARCHIVE_OUTPUT_NAME trick_pyip) + +# HDF5: -DHDF5 must reach the wrapper *compile*, not just SWIG. sim_services.i +# guards `#include "trick/DRHDF5.hh"` behind `#ifdef HDF5` — SWIG runs with +# -DHDF5 (via _tr_swig_defs above) so it emits code referencing Trick::DRHDF5, +# but if the generated wrapper is then compiled without -DHDF5 that same +# #ifdef skips the include and the class is undeclared ("no type named +# 'DRHDF5'"). Mirrors trick_swig/Makefile:4-5,38-42 (TRICK_CXXFLAGS += -DHDF5, +# plus -I$(HDF5)/include when HDF5 != /usr, since -DHDF5 then also activates +# DRHDF5.hh's own `#include "hdf5.h"`). +if(HDF5_HOME) + target_compile_definitions( trick_pyip PRIVATE HDF5 ) + target_link_libraries( trick_pyip PRIVATE trick::hdf5 ) +endif() + +# Makefile: trick_swig/Makefile:28-34 — SWIG-generated code triggers warnings +# the rest of the build treats as errors elsewhere; suppress the same set. +set(_tr_swig_wrap_opts -Wno-redundant-decls -Wno-shadow -Wno-unused-parameter -Wno-missing-field-initializers) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list(APPEND _tr_swig_wrap_opts -Wno-self-assign -Wno-sometimes-uninitialized) +else() + list(APPEND _tr_swig_wrap_opts -Wno-cast-function-type -Wno-ignored-qualifiers -Wno-delete-non-virtual-dtor) +endif() +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/sim_services_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_double_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_int_wrap.cpp + ${CMAKE_CURRENT_BINARY_DIR}/swig_ref_wrap.cpp + PROPERTIES COMPILE_OPTIONS "${_tr_swig_wrap_opts}" +) diff --git a/trick_source/trick_utils/CMakeLists.txt b/trick_source/trick_utils/CMakeLists.txt index d7941c5e9..ae014ef81 100644 --- a/trick_source/trick_utils/CMakeLists.txt +++ b/trick_source/trick_utils/CMakeLists.txt @@ -1,31 +1,31 @@ - - -# Trick utils files that are not in their own library +# Trick utils files that are not in their own library (top Makefile's +# UTILS_DIRS minus the dirs that build a separate archive, A3). set( TRICK_UTILS_SRC + compareFloatingPoint/src/compareFloatingPoint.cpp interpolator/src/Interpolator.cpp - shm/src/tsm_disconnect - shm/src/tsm_init - shm/src/tsm_init_with_lock - shm/src/tsm_reconnect - trick_adt/src/MapStrToPtr - trick_adt/src/bst - trick_adt/src/bubble_sort - trick_adt/src/dllist - trick_adt/src/lqueue - trick_adt/src/lstack - trick_adt/src/record_array - unicode/src/unicode_utils + shm/src/tsm_disconnect.c + shm/src/tsm_init.c + shm/src/tsm_init_with_lock.c + shm/src/tsm_reconnect.c + trick_adt/src/MapStrToPtr.c + trick_adt/src/bst.c + trick_adt/src/bubble_sort.c + trick_adt/src/dllist.c + trick_adt/src/lqueue.c + trick_adt/src/lstack.c + trick_adt/src/record_array.c + unicode/src/unicode_utils.c ) add_library( trick_utils_objs OBJECT ${TRICK_UTILS_SRC} ) +target_link_libraries( trick_utils_objs PUBLIC trick_build_flags ) ############################################################### -# Other Trick libraries +# Other Trick libraries (each packaged into its own archive, A3) ############################################################### add_subdirectory(comm) add_subdirectory(connection_handlers) add_subdirectory(math) +add_subdirectory(optimization) add_subdirectory(units) add_subdirectory(var_binary_parser) - - diff --git a/trick_source/trick_utils/SAIntegrator/.gitignore b/trick_source/trick_utils/SAIntegrator/.gitignore index 29f231ccc..9eb1a0efd 100644 --- a/trick_source/trick_utils/SAIntegrator/.gitignore +++ b/trick_source/trick_utils/SAIntegrator/.gitignore @@ -1,4 +1,3 @@ lib/ obj/ -*.o *.dSYM diff --git a/trick_source/trick_utils/comm/CMakeLists.txt b/trick_source/trick_utils/comm/CMakeLists.txt index 402f5b4bc..5002273ac 100644 --- a/trick_source/trick_utils/comm/CMakeLists.txt +++ b/trick_source/trick_utils/comm/CMakeLists.txt @@ -1,31 +1,33 @@ - set( TRICKCOMM_SRC - src/tc_accept - src/tc_blockio - src/tc_broadcast_conninfo - src/tc_clock_init - src/tc_clock_time - src/tc_connect - src/tc_dev_copy - src/tc_disconnect - src/tc_error - src/tc_init - src/tc_init_mcast_client - src/tc_init_mcast_server - src/tc_init_udp_client - src/tc_init_udp_server - src/tc_isValid - src/tc_listen - src/tc_multiconnect - src/tc_pending - src/tc_read - src/tc_read_byteswap - src/tc_set_blockio - src/tc_write - src/tc_write_byteswap - src/trick_bswap_buffer - src/trick_byteswap - src/trick_error_hndlr + src/tc_accept.c + src/tc_blockio.c + src/tc_broadcast_conninfo.c + src/tc_clock_init.c + src/tc_clock_time.c + src/tc_connect.c + src/tc_dev_copy.c + src/tc_disconnect.c + src/tc_error.c + src/tc_init.c + src/tc_init_mcast_client.c + src/tc_init_mcast_server.c + src/tc_init_udp_client.c + src/tc_init_udp_server.c + src/tc_isValid.c + src/tc_listen.c + src/tc_multiconnect.c + src/tc_pending.c + src/tc_read.c + src/tc_read_byteswap.c + src/tc_set_blockio.c + src/tc_write.c + src/tc_write_byteswap.c + src/trick_bswap_buffer.c + src/trick_bswap_single_parameter.c + src/trick_byteswap.c + src/trick_error_hndlr.c ) add_library( trick_comm STATIC ${TRICKCOMM_SRC}) +target_link_libraries( trick_comm PUBLIC trick_build_flags ) +set_target_properties( trick_comm PROPERTIES ARCHIVE_OUTPUT_NAME trick_comm) diff --git a/trick_source/trick_utils/compareFloatingPoint/test/.gitignore b/trick_source/trick_utils/compareFloatingPoint/test/.gitignore index da4626dac..d6459089c 100644 --- a/trick_source/trick_utils/compareFloatingPoint/test/.gitignore +++ b/trick_source/trick_utils/compareFloatingPoint/test/.gitignore @@ -1,2 +1 @@ -*.o *_unittest diff --git a/trick_source/trick_utils/connection_handlers/CMakeLists.txt b/trick_source/trick_utils/connection_handlers/CMakeLists.txt new file mode 100644 index 000000000..c007465ff --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/CMakeLists.txt @@ -0,0 +1,11 @@ +set( TRICK_CONNECTION_HANDLERS_SRC + ClientConnection.cpp + MulticastGroup.cpp + TCPClientListener.cpp + TCPConnection.cpp + UDPConnection.cpp +) + +add_library( trick_connection_handlers STATIC ${TRICK_CONNECTION_HANDLERS_SRC}) +target_link_libraries( trick_connection_handlers PUBLIC trick_build_flags ) +set_target_properties( trick_connection_handlers PROPERTIES ARCHIVE_OUTPUT_NAME trick_connection_handlers) diff --git a/trick_source/trick_utils/interpolator/test/.gitignore b/trick_source/trick_utils/interpolator/test/.gitignore index ad47b65c2..4051fb14e 100644 --- a/trick_source/trick_utils/interpolator/test/.gitignore +++ b/trick_source/trick_utils/interpolator/test/.gitignore @@ -1,2 +1 @@ -*.o Interpolator_unittest diff --git a/trick_source/trick_utils/math/CMakeLists.txt b/trick_source/trick_utils/math/CMakeLists.txt index ef40c4e40..0f3045791 100644 --- a/trick_source/trick_utils/math/CMakeLists.txt +++ b/trick_source/trick_utils/math/CMakeLists.txt @@ -1,96 +1,97 @@ - set( TRICKMATH_SRC - src/LUD_inv - src/LUT_inv - src/LU_bksb - src/LU_dcmp - src/RodriguesRotation - src/dLU_Choleski - src/dLU_solver - src/dS_function - src/deuler_123 - src/deuler_123_quat - src/deuler_132 - src/deuler_132_quat - src/deuler_213 - src/deuler_213_quat - src/deuler_231 - src/deuler_231_quat - src/deuler_312 - src/deuler_312_quat - src/deuler_321 - src/deuler_321_quat - src/dm_add - src/dm_copy - src/dm_ident - src/dm_init - src/dm_invert - src/dm_invert_symm - src/dm_orthonormal - src/dm_print - src/dm_scale - src/dm_sub - src/dm_trans - src/dmtxm - src/dmtxmt - src/dmtxv - src/dmxm - src/dmxmt - src/dmxv - src/drandom_gaussian - src/dsingle_axis_rot - src/dv_add - src/dv_copy - src/dv_cross - src/dv_dot - src/dv_init - src/dv_mag - src/dv_norm - src/dv_print - src/dv_scale - src/dv_skew - src/dv_store - src/dv_sub - src/dvxm - src/dvxv_add - src/dvxv_sub - src/eigen_hh_red - src/eigen_jacobi - src/eigen_jacobi_4 - src/eigen_ql - src/euler_matrix - src/euler_quat - src/gauss_rnd_bell - src/gauss_rnd_pseudo - src/mat_copy - src/mat_permute - src/mat_print - src/mat_to_quat - src/mat_trans - src/matxmat - src/matxtrans - src/matxvec - src/quat_mult - src/quat_norm - src/quat_norm_integ - src/quat_to_mat - src/rand_num - src/roundoff - src/tm_print_error - src/transxmat - src/transxtrans - src/transxvec - src/trick_gsl_rand - src/trns_fnct_1o - src/trns_fnct_2o - src/uniform_rnd_1 - src/uniform_rnd_triple - src/vec_print - src/wave_form + src/LUD_inv.c + src/LUT_inv.c + src/LU_bksb.c + src/LU_dcmp.c + src/RodriguesRotation.c + src/dLDLt_solver.c + src/dLU_Choleski.c + src/dLU_solver.c + src/dS_function.c + src/deuler_123.c + src/deuler_123_quat.c + src/deuler_132.c + src/deuler_132_quat.c + src/deuler_213.c + src/deuler_213_quat.c + src/deuler_231.c + src/deuler_231_quat.c + src/deuler_312.c + src/deuler_312_quat.c + src/deuler_321.c + src/deuler_321_quat.c + src/dm_add.c + src/dm_copy.c + src/dm_ident.c + src/dm_init.c + src/dm_invert.c + src/dm_invert_symm.c + src/dm_orthonormal.c + src/dm_print.c + src/dm_scale.c + src/dm_sub.c + src/dm_trans.c + src/dmtxm.c + src/dmtxmt.c + src/dmtxv.c + src/dmxm.c + src/dmxmt.c + src/dmxv.c + src/drandom_gaussian.c + src/dsingle_axis_rot.c + src/dv_add.c + src/dv_copy.c + src/dv_cross.c + src/dv_dot.c + src/dv_init.c + src/dv_mag.c + src/dv_norm.c + src/dv_print.c + src/dv_scale.c + src/dv_skew.c + src/dv_store.c + src/dv_sub.c + src/dvxm.c + src/dvxv_add.c + src/dvxv_sub.c + src/eigen_hh_red.c + src/eigen_jacobi.c + src/eigen_jacobi_4.c + src/eigen_ql.c + src/euler_matrix.c + src/euler_quat.c + src/gauss_rnd_bell.c + src/gauss_rnd_pseudo.c + src/mat_copy.c + src/mat_permute.c + src/mat_print.c + src/mat_to_quat.c + src/mat_trans.c + src/matxmat.c + src/matxtrans.c + src/matxvec.c + src/quat_mult.c + src/quat_norm.c + src/quat_norm_integ.c + src/quat_to_mat.c + src/rand_num.c + src/roundoff.c + src/tm_print_error.c + src/transxmat.c + src/transxtrans.c + src/transxvec.c + src/trick_gsl_rand.c + src/trns_fnct_1o.c + src/trns_fnct_2o.c + src/uniform_rnd_1.c + src/uniform_rnd_triple.c + src/vec_print.c + src/wave_form.c ) add_library( trick_math STATIC ${TRICKMATH_SRC}) - -if(GSL_FOUND) - target_include_directories( trick_math PUBLIC ${GSL_INCLUDE_DIRS} ) -endif() +target_link_libraries( trick_math PUBLIC trick_build_flags ) +set_target_properties( trick_math PROPERTIES ARCHIVE_OUTPUT_NAME trick_math) +# GSL flags (when GSL_HOME is set) come from trick_build_flags — Makefile.common +# puts them on TRICK_SYSTEM_CXXFLAGS globally, and math/Makefile has no local +# override, so it only ever gets them that way in the real build too. diff --git a/trick_source/trick_utils/math/test/.gitignore b/trick_source/trick_utils/math/test/.gitignore index f7b4fe9cf..75407e972 100644 --- a/trick_source/trick_utils/math/test/.gitignore +++ b/trick_source/trick_utils/math/test/.gitignore @@ -1,3 +1,2 @@ UnitTestEulerQuat UnitTestLDLtFactorization -*.o diff --git a/trick_source/trick_utils/optimization/CMakeLists.txt b/trick_source/trick_utils/optimization/CMakeLists.txt new file mode 100644 index 000000000..40872fd8c --- /dev/null +++ b/trick_source/trick_utils/optimization/CMakeLists.txt @@ -0,0 +1,7 @@ +set( TRICK_OPTIMIZATION_SRC + src/dPDIP_solver.c +) + +add_library( trick_optimization STATIC ${TRICK_OPTIMIZATION_SRC}) +target_link_libraries( trick_optimization PUBLIC trick_build_flags ) +set_target_properties( trick_optimization PROPERTIES ARCHIVE_OUTPUT_NAME trick_optimization) diff --git a/trick_source/trick_utils/optimization/test/.gitignore b/trick_source/trick_utils/optimization/test/.gitignore index 409295011..fcc715e44 100644 --- a/trick_source/trick_utils/optimization/test/.gitignore +++ b/trick_source/trick_utils/optimization/test/.gitignore @@ -1,2 +1 @@ UnitTestPDIPOptimization -*.o diff --git a/trick_source/trick_utils/trick_adt/test/.gitignore b/trick_source/trick_utils/trick_adt/test/.gitignore index 320de4928..491b116a1 100644 --- a/trick_source/trick_utils/trick_adt/test/.gitignore +++ b/trick_source/trick_utils/trick_adt/test/.gitignore @@ -1,3 +1,2 @@ -*.o dllist_unittest -lqueue_unittest \ No newline at end of file +lqueue_unittest diff --git a/trick_source/trick_utils/units/CMakeLists.txt b/trick_source/trick_utils/units/CMakeLists.txt index 613529c7f..dbdf9971f 100644 --- a/trick_source/trick_utils/units/CMakeLists.txt +++ b/trick_source/trick_utils/units/CMakeLists.txt @@ -1,9 +1,9 @@ - set( TRICK_UNITS_SRC src/UCFn.cpp src/Unit.cpp - src/units_conv + src/units_conv.c ) add_library( trick_units STATIC ${TRICK_UNITS_SRC}) - +target_link_libraries( trick_units PUBLIC trick_build_flags ) +set_target_properties( trick_units PROPERTIES ARCHIVE_OUTPUT_NAME trick_units) diff --git a/trick_source/trick_utils/units/test/.gitignore b/trick_source/trick_utils/units/test/.gitignore index cae4b199f..0ef033958 100644 --- a/trick_source/trick_utils/units/test/.gitignore +++ b/trick_source/trick_utils/units/test/.gitignore @@ -1,3 +1,2 @@ -*.o UnitConvTestSuite UnitTestSuite diff --git a/trick_source/trick_utils/var_binary_parser/.gitignore b/trick_source/trick_utils/var_binary_parser/.gitignore index 9e345c986..9a1296d5f 100644 --- a/trick_source/trick_utils/var_binary_parser/.gitignore +++ b/trick_source/trick_utils/var_binary_parser/.gitignore @@ -1,2 +1 @@ -*.o TEST_var_binary_parser diff --git a/trick_source/trick_utils/var_binary_parser/CMakeLists.txt b/trick_source/trick_utils/var_binary_parser/CMakeLists.txt new file mode 100644 index 000000000..460b3d6e4 --- /dev/null +++ b/trick_source/trick_utils/var_binary_parser/CMakeLists.txt @@ -0,0 +1,8 @@ +set( TRICK_VAR_BINARY_PARSER_SRC + src/var_binary_parser.cc +) + +add_library( trick_var_binary_parser STATIC ${TRICK_VAR_BINARY_PARSER_SRC}) +target_include_directories( trick_var_binary_parser PRIVATE ${CMAKE_SOURCE_DIR}/include ) +target_link_libraries( trick_var_binary_parser PUBLIC trick_build_flags ) +set_target_properties( trick_var_binary_parser PROPERTIES ARCHIVE_OUTPUT_NAME trick_var_binary_parser) diff --git a/trick_source/web/CivetServer/CMakeLists.txt b/trick_source/web/CivetServer/CMakeLists.txt new file mode 100644 index 000000000..f6ab97a3c --- /dev/null +++ b/trick_source/web/CivetServer/CMakeLists.txt @@ -0,0 +1,23 @@ +# libtrickCivet.a — Trick's native civetweb variable-server webserver, +# ported from this directory's own makefile (the authority). Only added to +# the build when USE_CIVETWEB is set (Phase 4, gated on TRICK_CIVETWEB_HOME +# detection in cmake/TrickPrograms.cmake). +# +# trick/MyCivetServer.hh (and this whole feature) is compiled out entirely +# unless USE_CIVETWEB is defined, mirroring Makefile.common:162-167's +# TRICK_SYSTEM_CXXFLAGS += -DUSE_CIVETWEB — trick_build_flags already adds +# that definition globally when USE_CIVETWEB is on (root CMakeLists.txt). + +add_library(trickCivet STATIC + src/MyCivetServer.cpp + src/VariableServerSession.cpp + src/VariableServerVariable.cpp + src/http_GET_handlers.cpp + src/simpleJSON.cpp +) +target_include_directories(trickCivet PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CIVETWEB_HOME}/include +) +target_link_libraries(trickCivet PUBLIC trick_build_flags) +set_target_properties(trickCivet PROPERTIES ARCHIVE_OUTPUT_NAME trickCivet) diff --git a/trickops.py b/trickops.py index cbe466e89..77ea582d7 100644 --- a/trickops.py +++ b/trickops.py @@ -1,97 +1,190 @@ -import sys +import argparse import os +import sys +from pathlib import Path -thisdir = os.path.abspath(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(os.path.join(thisdir,"share/trick/trickops")) +sys.path.append(str(Path(__file__).resolve().parent / "share" / "trick" / "trickops")) -from TrickWorkflow import * +from TrickWorkflow import TrickWorkflow from WorkflowCommon import Job +thisdir = Path(__file__).resolve().parent + max_retries = 5 + class SimTestWorkflow(TrickWorkflow): - def __init__( self, quiet, trick_top_level, cpus, config_file): + def __init__(self, quiet, trick_top_level, cpus, config_file, trick_dir=None): self.cpus = cpus + trick_top_level = Path(trick_top_level) + # Create the trick_test directory if it doesn't already exist - if not os.path.exists(trick_top_level + "/trick_test"): - os.makedirs(trick_top_level + "/trick_test") + (trick_top_level / "trick_test").mkdir(exist_ok=True) + + # trick_dir defaults to trick_top_level (historical behavior: sims and + # the installed Trick used by bin/trick-CP live in the same in-source + # tree). A CMake-driven test run passes them separately: sim + # directories (test/SIM_*) only exist in the source tree, but the + # installed product (bin/trick-CP, libexec/, share/) may be a staged + # out-of-source CMake install instead. + if trick_dir is None: + trick_dir = trick_top_level + else: + trick_dir = Path(trick_dir) # Base Class initialize, this creates internal management structures - TrickWorkflow.__init__(self, project_top_level=(trick_top_level), log_dir=(trick_top_level +'/trickops_logs/'), - trick_dir=trick_top_level, config_file=(trick_top_level + "/" + config_file), cpus=self.cpus, quiet=quiet) - def run( self ): - build_jobs = self.get_jobs(kind='build') - - # This is awful but I can't think of another way around it - # SIM_test_varserver has 2 tests that should return the code for SIGUSR1, the number is different on Mac vs Linux - # so it can't be hardcoded in the input yml file. Maybe this is a case having a label on a run would be cleaner? - import signal - run_names = ["Run test/SIM_test_varserv RUN_test/err1_test.py", "Run test/SIM_test_varserv RUN_test/err2_test.py"] - for job in [job for job in self.get_jobs(kind='run') if job.name in run_names]: - job._expected_exit_status = signal.SIGUSR1.value - - # Several test sims have runs that require ordering via phases: - # - SIM_stls dumps a checkpoint that is then read in and checked by a subsequent run - # - SIM_checkpoint_data_recording dumps checkpoints that are read by subsequent runs - # - SIM_test_varserver has 3 runs that cannot be concurrent - # - SIM_mc_generation generates runs and then runs them - phases = [-1, 0, 1, 2, 3] - - analysis_jobs = self.get_jobs(kind='analyze') - if platform == "darwin": - for job in build_jobs: - if job.name == "Build test/SIM_trickified_shared" : - print("REMOVING JOB: " + job.name) - build_jobs.remove(job) - builds_status = self.execute_jobs(build_jobs, max_concurrent=self.cpus, header='Executing all sim builds.') - - jobs = build_jobs - - run_status = 0 - for phase in phases: - run_jobs = self.get_jobs(kind='run', phase=phase) - if platform == "darwin": - for job in run_jobs: - if job.name == "Run test/SIM_trickified_shared RUN_test/unit_test.py" : - print("REMOVING JOB: " + job.name) - run_jobs.remove(job) - this_status = self.execute_jobs(run_jobs, max_concurrent=self.cpus, header="Executing phase " + str(phase) + " runs.", job_timeout=1000) - run_status = run_status or this_status - jobs += run_jobs - - comparison_result = self.compare() - analysis_status = self.execute_jobs(analysis_jobs, max_concurrent=self.cpus, header='Executing all analysis.') - - self.report() # Print Verbose report - self.status_summary() # Print a Succinct summary - - # Dump failing logs - for job in jobs: - if job.get_status() == Job.Status.FAILED or job.get_status() == Job.Status.TIMEOUT: - print ("*"*120) - if job.get_status() == Job.Status.FAILED: - header = "Failing job: " + job.name - else: - header = "Timed out job: " + job.name - - numspaces = int((120 - 20 - len(header))/2 -2) - print("*"*10, " "*numspaces, header, " "*numspaces, "*"*10,) - print ("*"*120) - print(open(job.log_file, "r").read()) - print ("*"*120, "\n\n\n") - - return (builds_status or run_status or len(self.config_errors) > 0 or comparison_result or analysis_status) + TrickWorkflow.__init__( + self, + project_top_level=str(trick_top_level), + log_dir=str(trick_top_level / "trickops_logs"), + trick_dir=str(trick_dir), + config_file=str(trick_top_level / config_file), + cpus=self.cpus, + quiet=quiet, + ) + + def run(self): + build_jobs = self.get_jobs(kind="build") + + # This is awful but I can't think of another way around it + # SIM_test_varserver has 2 tests that should return the code for SIGUSR1, the number is different on Mac vs Linux + # so it can't be hardcoded in the input yml file. Maybe this is a case having a label on a run would be cleaner? + import signal + + run_names = [ + "Run test/SIM_test_varserv RUN_test/err1_test.py", + "Run test/SIM_test_varserv RUN_test/err2_test.py", + ] + for job in [job for job in self.get_jobs(kind="run") if job.name in run_names]: + job._expected_exit_status = signal.SIGUSR1.value + + # Several test sims have runs that require ordering via phases: + # - SIM_stls dumps a checkpoint that is then read in and checked by a subsequent run + # - SIM_checkpoint_data_recording dumps checkpoints that are read by subsequent runs + # - SIM_test_varserver has 3 runs that cannot be concurrent + # - SIM_mc_generation generates runs and then runs them + phases = [-1, 0, 1, 2, 3] + + analysis_jobs = self.get_jobs(kind="analyze") + if self.platform == "darwin": + for job in build_jobs: + if job.name == "Build test/SIM_trickified_shared": + print("REMOVING JOB: " + job.name) + build_jobs.remove(job) + builds_status = self.execute_jobs( + build_jobs, max_concurrent=self.cpus, header="Executing all sim builds." + ) + + jobs = build_jobs + + run_status = 0 + for phase in phases: + run_jobs = self.get_jobs(kind="run", phase=phase) + if self.platform == "darwin": + for job in run_jobs: + if ( + job.name + == "Run test/SIM_trickified_shared RUN_test/unit_test.py" + ): + print("REMOVING JOB: " + job.name) + run_jobs.remove(job) + this_status = self.execute_jobs( + run_jobs, + max_concurrent=self.cpus, + header="Executing phase " + str(phase) + " runs.", + job_timeout=1000, + ) + run_status = run_status or this_status + jobs += run_jobs + + comparison_result = self.compare() + analysis_status = self.execute_jobs( + analysis_jobs, max_concurrent=self.cpus, header="Executing all analysis." + ) + + self.report() # Print Verbose report + self.status_summary() # Print a Succinct summary + + # Dump failing logs + for job in jobs: + if ( + job.get_status() == Job.Status.FAILED + or job.get_status() == Job.Status.TIMEOUT + ): + print("*" * 120) + if job.get_status() == Job.Status.FAILED: + header = "Failing job: " + job.name + else: + header = "Timed out job: " + job.name + + numspaces = int((120 - 20 - len(header)) / 2 - 2) + print( + "*" * 10, + " " * numspaces, + header, + " " * numspaces, + "*" * 10, + ) + print("*" * 120) + print(Path(job.log_file).read_text()) + print("*" * 120, "\n\n\n") + + return ( + builds_status + or run_status + or len(self.config_errors) > 0 + or comparison_result + or analysis_status + ) + if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Build, run, and compare all test sims for Trick', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( "--trick_top_level", type=str, help="Path to TRICK_HOME", default=thisdir) - parser.add_argument( "--quiet", action="store_true", help="Suppress progress bars (automatically set to True if environment variable CI is present).") - parser.add_argument( "--cpus", type=int, default=(os.cpu_count() if os.cpu_count() is not None else 8), - help="Number of cpus to use for testing. For builds this number is used for MAKEFLAGS *and* number of " - "concurrent builds (cpus^2). For sim runs this controls the maximum number of simultaneous runs.") - parser.add_argument( "--config_file", type=str, help="Run configuration file to use, relative to trick_top_level", default="test_sims.yml") + parser = argparse.ArgumentParser( + description="Build, run, and compare all test sims for Trick", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "--trick_top_level", + type=str, + help="Path to the project tree containing the sim " + "directories referenced by --config_file", + default=str(thisdir), + ) + parser.add_argument( + "--trick_dir", + type=str, + help="Path to the installed/staged Trick (bin/trick-CP, " + "libexec/, share/) used to build the sims. Defaults to --trick_top_level (historical in-source " + "behavior, where sims and the Trick install share one tree).", + default=None, + ) + parser.add_argument( + "--quiet", + action="store_true", + help="Suppress progress bars (automatically set to True if environment variable CI is present).", + ) + parser.add_argument( + "--cpus", + type=int, + default=(os.cpu_count() if os.cpu_count() is not None else 8), + help="Number of cpus to use for testing. For builds this number is used for MAKEFLAGS *and* number of " + "concurrent builds (cpus^2). For sim runs this controls the maximum number of simultaneous runs.", + ) + parser.add_argument( + "--config_file", + type=str, + help="Run configuration file to use, relative to trick_top_level", + default="test_sims.yml", + ) myargs = parser.parse_args() - should_be_quiet = myargs.quiet or os.getenv('CI') is not None - sys.exit(SimTestWorkflow(quiet=should_be_quiet, trick_top_level=myargs.trick_top_level, cpus=myargs.cpus, config_file=myargs.config_file).run()) + should_be_quiet = myargs.quiet or os.getenv("CI") is not None + sys.exit( + SimTestWorkflow( + quiet=should_be_quiet, + trick_top_level=myargs.trick_top_level, + trick_dir=myargs.trick_dir, + cpus=myargs.cpus, + config_file=myargs.config_file, + ).run() + )