diff --git a/CMakeLists.txt b/CMakeLists.txt index e09e2594..789c32fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,13 +131,42 @@ target_link_libraries(cml_static PRIVATE $<$:--coverage> ) -target_link_libraries(cml_shared - PUBLIC - LibXml2::LibXml2 - $<$:-fsanitize=address,undefined> - PRIVATE - $<$:--coverage> -) + +if(APPLE) + message(STATUS "Configuring macOS-specific linking for cml_shared") + + target_link_libraries(cml_shared + PUBLIC + LibXml2::LibXml2 + ${JEOD_LIBRARY} + ${Trick_LIBRARY} + ${Trick_liber7_utils} + ${Trick_libtrick_mm} + ${Trick_libtrick_math} + ${Trick_libtrick_comm} + ${Trick_libtrick_connection_handlers} + ${Trick_libtrick_units} + ${Trick_libtrick_pyip} + /opt/homebrew/lib/libudunits2.dylib + ${Trick_libtrick_var_binary_parser} + ${Trick_libconversions} + PRIVATE + $<$:--coverage> + ) + +else() + message(STATUS "Configuring Linux-specific linking for cml_shared") + + # Linux does NOT require explicit Trick/JEOD linking for shared libraries + target_link_libraries(cml_shared + PUBLIC + LibXml2::LibXml2 + $<$:-fsanitize=address,undefined> + PRIVATE + $<$:--coverage> + ) + +endif() # Set include directories for libcml. This is mostly for unit test executables # that rely on libcml. diff --git a/bin/test.py b/bin/test.py index e47f3666..65a75264 100755 --- a/bin/test.py +++ b/bin/test.py @@ -42,30 +42,13 @@ def _parse_args(): def _verify_args(args): ''' - Ensure Trick and JEOD areas exist and libs are built. If they aren't, all tests will fail + Ensure JEOD areas exist and libs are built. If they aren't, all tests will fail ''' - if not args.trick or not os.path.exists(args.trick): - msg = ("Unable to locate trick directory. Define TRICK_HOME in your environment" - " or use --trick=/path/to/trick/ to specify a path to a pre-built Trick" - " directory (Requires version 19.5.1 or later)") - raise RuntimeError(msg) - if (not os.path.exists(os.path.join(args.trick, 'lib64')) or - not os.listdir(os.path.join(args.trick,'lib64'))): - msg = (f"Specified trick directory {args.trick} is missing built libraries. " - "Build trick for this platform to resolve this error.") - raise RuntimeError(msg) - if not args.jeod or not os.path.exists(args.jeod): - msg = ("Unable to locate JEOD directory. Define JEOD_HOME in your environment" - " or use --jeod=/path/to/jeod/ to specify a path to a JEOD" - " directory (Requires version 3.4 or later)") - raise RuntimeError(msg) # We need to know what TRICK_HOST_CPU is to find the libraries, so get that first cmd = ( os.path.join(args.trick, 'bin/trick-gte') + " TRICK_HOST_CPU") sys.path.append(os.path.abspath(os.path.join(args.trick, 'share/trick/trickops/'))) from WorkflowCommon import run_subprocess trick_host_cpu = run_subprocess(command=cmd,m_shell=True).stdout.strip().split("\n")[-1] - if not os.path.isfile(os.path.join(args.trick, 'lib64/libtrick.a')): - raise RuntimeError(f"Trick hasn't been built. Build {args.trick} and try again.") if not os.path.isfile(os.path.join(args.jeod, 'lib_jeod_' + trick_host_cpu + '/libjeod.a' )): raise RuntimeError(f"JEOD library under {args.jeod} hasn't been built. See README.md for instructions and try again.") if not os.path.isfile(os.path.join(args.jeod, f'trickified/trickified_jeod_{trick_host_cpu}.o')): @@ -74,7 +57,7 @@ def _verify_args(args): if len(ephem_files) < 1: raise RuntimeError(f"JEOD ephemeris files under {args.jeod} haven't been built. See README.md for instructions and try again.") - return args + return args # Argparsing must happen at global scope since we can't import TrickOps without # figuring out the location of Trick, which can be passed in to this script. diff --git a/cmake/SetCMLCompileWarnings.cmake b/cmake/SetCMLCompileWarnings.cmake index fd373523..22c60622 100644 --- a/cmake/SetCMLCompileWarnings.cmake +++ b/cmake/SetCMLCompileWarnings.cmake @@ -12,6 +12,11 @@ include_guard() function(set_cml_compile_warnings TARGET) + # If the compiler is GCC, continue. Otherwise, return immediately. + if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + return() + endif() + set(CML_SHARED_WARNING_FLAGS # Keep these first since we may override some of the levels set for # certain warnings below. diff --git a/mkspecs/cml.mk b/mkspecs/cml.mk index bb63ae6d..a73f5b33 100644 --- a/mkspecs/cml.mk +++ b/mkspecs/cml.mk @@ -58,7 +58,7 @@ endif TRICK_CXXFLAGS += -I${CML_HOME}/.. -D_USE_MATH_DEFINES TRICK_CFLAGS += -I${CML_HOME}/.. -D_USE_MATH_DEFINES -# Include paths and libraries for libxml2 +# Include paths and libraries for libxml2 for linux ifeq ($(shell pkg-config --exists libxml-2.0 && echo $$?),0) TRICK_CXXFLAGS += $(shell pkg-config libxml-2.0 --cflags) TRICK_LDFLAGS += $(shell pkg-config libxml-2.0 --libs) diff --git a/mkspecs/internal/cml_lib.mk b/mkspecs/internal/cml_lib.mk index adcde7ec..3066074c 100644 --- a/mkspecs/internal/cml_lib.mk +++ b/mkspecs/internal/cml_lib.mk @@ -88,6 +88,8 @@ TRICK_EXT_LIB_DIRS += :${CML_SOURCE_DIRS} TRICK_LDFLAGS += -L${CML_LIBRARY_DIR} ifeq (1, $(CML_USE_STATIC_LIB)) TRICK_LDFLAGS += -l:libcml.a +else ifeq ($(shell trick-gte TRICK_HOST_CPU), Darwin_25) + TRICK_LDFLAGS += -Wl,-rpath,${CML_LIBRARY_DIR} -lcml else TRICK_LDFLAGS += -Wl,-rpath=${CML_LIBRARY_DIR} -lcml endif diff --git a/mkspecs/internal/cml_unit_sim.mk b/mkspecs/internal/cml_unit_sim.mk index 6b3659aa..e8b43c3a 100644 --- a/mkspecs/internal/cml_unit_sim.mk +++ b/mkspecs/internal/cml_unit_sim.mk @@ -11,6 +11,29 @@ CML_BUILD_DEBUG := 1 include ${CML_HOME}/mkspecs/cml.mk include ${CML_HOME}/mkspecs/internal/jeod.mk +# temporary fix for Mac as -Wno-nonnull-compare is not recognized by clang +TRICK_CFLAGS += -g -I. -Wall -Wextra -Werror -Wno-implicit-fallthrough -Wno-format-truncation -Wno-int-in-bool-context -Wno-address +TRICK_CXXFLAGS += -g -I. -Wall -Wextra -Werror -Wno-implicit-fallthrough -Wno-format-truncation -Wno-int-in-bool-context -Wno-address +TRICK_SFLAGS += -I${JEOD_HOME}/lib/jeod/JEOD_S_modules -I. + +# Try adding -Wno-nonnull-compare only if the compiler supports it +CHECK_CXXFLAG = $(shell \ + $(CXX) -Werror=unknown-warning-option -Wno-nonnull-compare -E - < /dev/null \ + >/dev/null 2>&1 && echo yes || echo no) + +ifeq ($(CHECK_CXXFLAG),yes) +TRICK_CFLAGS += -Wno-nonnull-compare +TRICK_CXXFLAGS += -Wno-nonnull-compare +endif + +# Remove after JEOD 5: +TRICK_CXXFLAGS += -I${JEOD_HOME}/models -I${JEOD_HOME}/.. + +# Strip unneeded -lint from TRICK_EXEC_LINK_LIBS. This originates from python3-config +# and appears to be part of the FSL spack-installed version of python3.X only +# If we can understand/resolve the core issue, this can be removed. +# See: https://gitlab-fsl.jsc.nasa.gov/FSL/Documentation/-/issues/1111 -Jordan 4/2024 +TRICK_EXEC_LINK_LIBS := $(filter-out -lintl,$(TRICK_EXEC_LINK_LIBS)) TRICK_CFLAGS += -g -I. -Wall -Wextra -Werror TRICK_CXXFLAGS += -g -I. -std=c++17 -Wall -Wextra -Werror TRICK_SFLAGS += -I${JEOD_HOME}/lib/jeod/JEOD_S_modules -I. @@ -21,3 +44,25 @@ TRICK_CXXFLAGS += -fsanitize=address,undefined TRICK_LDFLAGS += -fsanitize=address,undefined TRICK_CXXFLAGS += -I${JEOD_HOME}/.. + +# ============================================================ +# macOS (Darwin) specific fixes +# ============================================================ +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) + +# ------------------------------------------------------------ +# 1. Strip Trick's auto-added -std=c++11 and -std=c++14 +# 2. Add -Wno-overloaded-virtual to Apple builds +# ------------------------------------------------------------ +TRICK_IO_CXXFLAGS := $(filter-out -std=c++11 -std=c++14,$(TRICK_IO_CXXFLAGS)) +TRICK_IO_CXXFLAGS += -std=c++17 + +TRICK_CXXFLAGS := $(filter-out -std=c++11 -std=c++14,$(TRICK_CXXFLAGS)) +TRICK_CXXFLAGS += -std=c++17 + +TRICK_CXXFLAGS += -Wno-overloaded-virtual +TRICK_CFLAGS += -Wno-overloaded-virtual +TRICK_IO_CXXFLAGS += -Wno-overloaded-virtual + +endif diff --git a/models/dynamics/state_predictors/impact_point/include/impact_point.hh b/models/dynamics/state_predictors/impact_point/include/impact_point.hh index 126fe708..a61e631c 100644 --- a/models/dynamics/state_predictors/impact_point/include/impact_point.hh +++ b/models/dynamics/state_predictors/impact_point/include/impact_point.hh @@ -19,7 +19,7 @@ PROGRAMMERS: (New implementation of ball_impact for Antares)) ((Bingquan Wang) (OSR) (May 2014) (cleaned up the code per its IV&V code review)) - ) + ) ******************************************************************************/ #ifndef CML_IMPACT_POINT_HH @@ -34,12 +34,12 @@ PROGRAMMERS: // Forward declaration class RefFrameTrans; -class ImpactPoint : public jeod::PlanetFixedPosition, - public SubscriptionBase +class ImpactPoint : public jeod::PlanetFixedPosition, + public SubscriptionBase { protected: const double & dyn_time; /* (s) Reference to the simulation's dynamic time.*/ - const jeod::Planet & planet_ref; /* (--) + const jeod::Planet & planet_ref; /* (--) Reference to the central planet. Note - planet_ref is the reference; "planet" is a pointer to the same place that is inherited from PlanetFixedPosition but is not used in this model. */ @@ -60,7 +60,7 @@ class ImpactPoint : public jeod::PlanetFixedPosition, //INPUT bool auto_off; /* (--) Turns off automatically when vehicle hits the ground */ - double iteration_threshold; /* (m) + double iteration_threshold; /* (m) The threshold distance between the orbital position and the planet surface at which the iteration is considered to have converged. */ unsigned int iteration_count_max; /* (--) max number of iterations */ @@ -70,7 +70,7 @@ class ImpactPoint : public jeod::PlanetFixedPosition, double time_to_impact; /* (s) Time until impact */ double time_of_impact; /* (s) Simulation dynamic time of predicted impact. */ ImpactType impact_type; /* (--) Identifies type of impact. */ - RangeFromPfixReference launch_range; /* (--) + RangeFromPfixReference launch_range; /* (--) The range from the reference point, typically the launch site. */ protected: @@ -86,7 +86,7 @@ class ImpactPoint : public jeod::PlanetFixedPosition, const jeod::Planet & planet, const double & grav_mu); ~ImpactPoint() override = default; - + void initialize() override; void initialize( double ref_pos[3]); void update(); @@ -103,5 +103,5 @@ class ImpactPoint : public jeod::PlanetFixedPosition, ImpactPoint(const ImpactPoint&); ImpactPoint & operator = (const ImpactPoint&); }; - + #endif diff --git a/models/fhw/effectors/springs/include/mass_body_detach_with_springs.hh b/models/fhw/effectors/springs/include/mass_body_detach_with_springs.hh index c8a71b62..18af8b23 100644 --- a/models/fhw/effectors/springs/include/mass_body_detach_with_springs.hh +++ b/models/fhw/effectors/springs/include/mass_body_detach_with_springs.hh @@ -39,6 +39,7 @@ public: // NOTE - initialize(jeod::DynManager) is called from Dynamics Manager as a // consequence of adding this body action with the add_body_action method // call. + using jeod::BodyDetach::initialize; void initialize( const jeod::DynBody & parent, SeparationState & sep_state) { @@ -97,7 +98,7 @@ public: }; void apply( jeod::DynManager & dyn_manager) override - { + { springs.action_body_is_child = child_is_action_body; springs.activate(); jeod::BodyDetach::apply(dyn_manager); diff --git a/models/interactions/aero/include/aero_executive_table.hh b/models/interactions/aero/include/aero_executive_table.hh index 6c13682b..982d6cae 100644 --- a/models/interactions/aero/include/aero_executive_table.hh +++ b/models/interactions/aero/include/aero_executive_table.hh @@ -178,6 +178,7 @@ public: void update() override; protected: void activate() override; + void configure_new_table(AeroTableSetBase *); void trig_functions(); void post_process_table_data(); diff --git a/models/interactions/aero/include/aero_interface_table.hh b/models/interactions/aero/include/aero_interface_table.hh index 5d4ec208..bd902274 100644 --- a/models/interactions/aero/include/aero_interface_table.hh +++ b/models/interactions/aero/include/aero_interface_table.hh @@ -43,6 +43,7 @@ public: void initialize() override; void update() override; + protected: void activate() override; void deactivate() override; diff --git a/models/utilities/buffers/verif/SIM_tagged_ring_buffer/sample_class.hh b/models/utilities/buffers/verif/SIM_tagged_ring_buffer/sample_class.hh index 7721b29a..6f040a59 100644 --- a/models/utilities/buffers/verif/SIM_tagged_ring_buffer/sample_class.hh +++ b/models/utilities/buffers/verif/SIM_tagged_ring_buffer/sample_class.hh @@ -16,7 +16,16 @@ struct TestStruc double x; int i; TestStruc() : x(1.1), i(1){}; - TestStruc( const TestStruc & rhs) = default; + TestStruc( const TestStruc & rhs) : x(rhs.x), i(rhs.i){}; + TestStruc& operator=(const TestStruc& rhs) + { + if (this != &rhs) + { + x = rhs.x; + i = rhs.i; + } + return *this; + } }; struct SampleModel diff --git a/models/utilities/constraint_check/include/threshold_constraint.hh b/models/utilities/constraint_check/include/threshold_constraint.hh index 818f308e..985456cf 100644 --- a/models/utilities/constraint_check/include/threshold_constraint.hh +++ b/models/utilities/constraint_check/include/threshold_constraint.hh @@ -509,7 +509,7 @@ class ThresholdTimedConstraintSpecData : public Constraint (num_specs-1) and fraction 0 by definition. - The first and last test values have already been assigned. - The highest value of any other mapped-index is num_specs-2.*/ - size_t mapped_ix[num_tests-1]; + std::vector mapped_ix(num_tests-1); mapped_ix[0] = 0; // unused spacer, we already have values for test-0. size_t spec_ix=0; for (size_t test_ix = 1; test_ix <= num_tests-2; ++test_ix) { @@ -577,7 +577,7 @@ class ThresholdTimedConstraintSpecData : public Constraint * redundant repetition (typically, we are adding more tests than * specified, so the same spec-ix will be used multiple times). * lg_ratio[i] = lg (threshold[i+1] / threshold[i]) */ - double log_threshold_ratios[num_specs-1]; + std::vector log_threshold_ratios(num_specs-1); for (spec_ix = 0; spec_ix <= num_specs-2; ++spec_ix) { log_threshold_ratios[spec_ix] = std::log10( threshold_spec[spec_ix+1] / threshold_spec[spec_ix]); diff --git a/models/utilities/math_utils/include/math_utils.hh b/models/utilities/math_utils/include/math_utils.hh index 01f5e194..eb91d62c 100644 --- a/models/utilities/math_utils/include/math_utils.hh +++ b/models/utilities/math_utils/include/math_utils.hh @@ -236,7 +236,7 @@ public: return false; } return ((val2 > val1) ? - val1 + tol >= val2 : + val1 + tol >= val2 : val2 + tol >= val1); } template @@ -310,11 +310,11 @@ public: { return MathUtilsPrivate::asin_fp(val); } - + /* TODO Hirad Mirhashemi 2025/10. * DEPRECATED CONTENT. Remove after reasonable timeframe.*/ - static float sqrt( float val) - { + static float sqrt( float val) + { CMLMessage::inform(__FILE__,__LINE__, "Deprecated method used: sqrt.\n" "This method name was not sufficiently descriptive.\n" @@ -322,7 +322,7 @@ public: return sqrt_protected(val); } static double sqrt( double val) - { + { CMLMessage::inform(__FILE__,__LINE__, "Deprecated method used: sqrt.\n" "This method name was not sufficiently descriptive.\n" @@ -975,7 +975,7 @@ Purpose: // [in] = [C_decomp] * [C_decomp]' => [inv(in)] = [inv(C)]' * [inv(C)] // and the inverse of the decomposed matrix is arithmetically simple to // compute. - double C_inv[dimension][dimension] = {0}; + double C_inv[dimension][dimension] = {}; for ( size_t ii = 0; ii < dimension; ii++) { // Note -- division by zero already checked above and method has // returned if any diagonal elements are zero. diff --git a/models/utilities/math_utils/include/math_utils_private.hh b/models/utilities/math_utils/include/math_utils_private.hh index 028b2b4f..0f73624a 100644 --- a/models/utilities/math_utils/include/math_utils_private.hh +++ b/models/utilities/math_utils/include/math_utils_private.hh @@ -4,7 +4,7 @@ #include #include // abs, isnan, isinf #include // std::max, min -#include // fp exception +#include // fp exception #include // std::numeric_limits::min, epsilon #include "cml/models/utilities/cml_message/include/cml_message.hh" @@ -34,8 +34,9 @@ class MathUtilsPrivate { const T val2, const T ulp) { + std::fenv_t env; //temporary disable fp exceptions - const int fe_prev = fedisableexcept(FE_ALL_EXCEPT); + const int fe_prev = std::feholdexcept(&env); assert(-1 != fe_prev); const T abs_val1 = std::abs(val1); @@ -59,7 +60,7 @@ class MathUtilsPrivate { ); } - feenableexcept(fe_prev); // restore the previous settings of fp exceptions + std::fesetenv(&env); // restore the previous settings of fp exceptions return res; } @@ -73,9 +74,10 @@ class MathUtilsPrivate { const T failed_val, const bool failed_flag) { + std::fenv_t env; // Temporary disable fp exceptions, storing the // set of previously configured exceptions. - const int fe_prev = fedisableexcept(FE_ALL_EXCEPT); + const int fe_prev = std::feholdexcept(&env); assert(-1 != fe_prev); // If -1, there was a failure T res = dividend/divisor; @@ -101,7 +103,7 @@ class MathUtilsPrivate { res = failed_val; } - feenableexcept(fe_prev); // restore the previous settings of fp exceptions + std::fesetenv(&env); // restore the previous settings of fp exceptions return res; } @@ -165,9 +167,10 @@ class MathUtilsPrivate { const bool failed_flag, const bool base10) { + std::fenv_t env; // Temporary disable fp exceptions, storing the set of // previously configured exceptions. - const int fe_prev = fedisableexcept(FE_ALL_EXCEPT); + const int fe_prev = std::feholdexcept(&env); assert(-1 != fe_prev); // If -1, there was a failure T res; @@ -189,7 +192,7 @@ class MathUtilsPrivate { } } - feenableexcept(fe_prev); // restore the previous settings of fp exceptions + std::fesetenv(&env); // restore the previous settings of fp exceptions return res; } }; diff --git a/models/utilities/math_utils/src/math_utils.cc b/models/utilities/math_utils/src/math_utils.cc index e7c74179..271bcfa3 100644 --- a/models/utilities/math_utils/src/math_utils.cc +++ b/models/utilities/math_utils/src/math_utils.cc @@ -600,9 +600,10 @@ MathUtils::polynomial( double x, const double failed_val, const bool failed_flag) { + std::fenv_t env; // Temporary disable fp exceptions, storing the set of // previously configured exceptions. - const int fe_prev = fedisableexcept(FE_ALL_EXCEPT); + const int fe_prev = std::feholdexcept(&env); assert(-1 != fe_prev); // If -1, there was a failure double x_to_i = 1.0; @@ -629,7 +630,7 @@ MathUtils::polynomial( double x, } sum = failed_val; } - feenableexcept(fe_prev); // restore the previous settings of fp exceptions + std::fesetenv(&env); // restore the previous settings of fp exceptions return sum; } diff --git a/models/utilities/table_interp_cpp/verif/SIM_02_simple_table_lookup/S_define b/models/utilities/table_interp_cpp/verif/SIM_02_simple_table_lookup/S_define index 36a11763..7e5d47b8 100644 --- a/models/utilities/table_interp_cpp/verif/SIM_02_simple_table_lookup/S_define +++ b/models/utilities/table_interp_cpp/verif/SIM_02_simple_table_lookup/S_define @@ -14,7 +14,7 @@ Descending data runs with only 1 dependent while ascending data runs with 2 to p class TestingModelSimObject : public Trick::SimObject { public: double independent; - double dependent[11][2]; // (--) 11 tables, 2 data per table + double dependent[12][2]; // (--) 12 tables, 2 data per table double indep_incr; // (--) increment per cycle. int frame_count; int reverse_on_count; diff --git a/models/vehicle_management/events_manager/include/watch_values_base_core.hh b/models/vehicle_management/events_manager/include/watch_values_base_core.hh index c9219321..9deb8eb3 100644 --- a/models/vehicle_management/events_manager/include/watch_values_base_core.hh +++ b/models/vehicle_management/events_manager/include/watch_values_base_core.hh @@ -65,7 +65,7 @@ class WatchValuesBaseCore : public SubscriptionBase { std::string name; /* (--) Name, primarily for debugging purposes. May be left blank.*/ bool locked; /* (--) - Boolean used to lock at each cycle, so each WatchValuesBase cannot be + Boolean used to lock at each cycle, so each WatchValuesBase cannot be tested more than once per cycle, leading to unintended behavior.*/ bool externally_managed; /* (--) Boolean setting that bool "locked" is set to once trigger is evaluated diff --git a/trickified/makefile b/trickified/makefile index 4c5a4f15..23330928 100644 --- a/trickified/makefile +++ b/trickified/makefile @@ -9,9 +9,6 @@ export TRICKIFY_EXT_LIB_DIRS += :${JEOD_HOME}/models export TRICKIFY_PYTHON_DIR := python.zip export ICG_EXCLUDE += :${JEOD_HOME}/models -ifeq ($(shell pkg-config --exists libxml-2.0 && echo $$?),0) - export TRICKIFY_CXX_FLAGS += $(shell pkg-config libxml-2.0 --cflags) -endif # Due to limitations with Trickification and SWIG, the JEOD Trickified library # and build artifacts MUST exist for CML to Trickify properly.