First release
- Added build script and AMPL license file - Fixed merge errors for the makefile - Extended the makefile header - Added initial AMQ message topics - Tested remote build - Removed AMPL license file - Validated build script - Accepting the metric definition message from the EMS - Execution control status messages + solver type command line option - Executing solver component - Added instructions on use to the Solver Component source file - Explicit close of subscriptions in destrcutors if network active. - Correct handling of metric list messages and subscriptions - Adding correct message and connection properties Change-Id: If02caff12aacf8a2181c96eb6dca4a19dc23c118
This commit is contained in:
parent
ae588d8955
commit
44d093d2f8
13
.vscode/c_cpp_properties.json
vendored
13
.vscode/c_cpp_properties.json
vendored
@ -3,19 +3,15 @@
|
|||||||
{
|
{
|
||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13",
|
|
||||||
"/home/GHo/Documents/Code/CxxOpts/include",
|
"/home/GHo/Documents/Code/CxxOpts/include",
|
||||||
"/home/GHo/Documents/Code/Theron++",
|
"/home/GHo/Documents/Code/Theron++",
|
||||||
"/home/GHo/Documents/Code/Theron++/Utility",
|
|
||||||
"/home/GHo/Documents/Code/Theron++/Communication",
|
|
||||||
"/home/GHo/Documents/Code/Theron++/Communication/AMQ",
|
|
||||||
"/opt/AMPL/amplapi/include/ampl",
|
"/opt/AMPL/amplapi/include/ampl",
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/home/GHo/Documents/Code/Theron++"
|
"/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"cStandard": "c23",
|
"cStandard": "c23",
|
||||||
"intelliSenseMode": "linux-gcc-x64",
|
"intelliSenseMode": "${default}",
|
||||||
"compilerPath": "/usr/bin/g++",
|
"compilerPath": "/usr/bin/g++",
|
||||||
"compilerArgs": [
|
"compilerArgs": [
|
||||||
"-std=c++23",
|
"-std=c++23",
|
||||||
@ -28,12 +24,9 @@
|
|||||||
"configurationProvider": "ms-vscode.makefile-tools",
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
"browse": {
|
"browse": {
|
||||||
"path": [
|
"path": [
|
||||||
"/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13",
|
|
||||||
"/home/GHo/Documents/Code/Theron++",
|
"/home/GHo/Documents/Code/Theron++",
|
||||||
"/home/GHo/Documents/Code/CxxOpts/include",
|
"/home/GHo/Documents/Code/CxxOpts/include",
|
||||||
"/home/GHo/Documents/Code/Theron++/Utility",
|
"/usr/lib/gcc/x86_64-redhat-linux/13/../../../../include/c++/13"
|
||||||
"/home/GHo/Documents/Code/Theron++/Communication",
|
|
||||||
"/home/GHo/Documents/Code/Theron++/Examples"
|
|
||||||
],
|
],
|
||||||
"limitSymbolsToIncludedHeaders": false
|
"limitSymbolsToIncludedHeaders": false
|
||||||
}
|
}
|
||||||
|
1
AMPLTest/.gitignore
vendored
Normal file
1
AMPLTest/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.ampl
|
@ -68,7 +68,7 @@ void ExecutionControl::StopMessageHandler( const StopMessage & Command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Constructor
|
// Constructor & destructor
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// The constructor registers the stop message handler and sets up a publisher
|
// The constructor registers the stop message handler and sets up a publisher
|
||||||
@ -91,4 +91,16 @@ ExecutionControl::ExecutionControl( const std::string & TheActorName )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The destructor simply closes the publisher if the network is still active
|
||||||
|
// when the actor closes.
|
||||||
|
|
||||||
|
ExecutionControl::~ExecutionControl( void )
|
||||||
|
{
|
||||||
|
if( HasNetwork() )
|
||||||
|
Send( Theron::AMQ::NetworkLayer::TopicSubscription(
|
||||||
|
Theron::AMQ::NetworkLayer::TopicSubscription::Action::ClosePublisher,
|
||||||
|
std::string( StatusTopic )
|
||||||
|
), GetSessionLayerAddress() );
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NebulOuS
|
} // namespace NebulOuS
|
@ -167,7 +167,7 @@ public:
|
|||||||
ExecutionControl( const std::string & TheActorName );
|
ExecutionControl( const std::string & TheActorName );
|
||||||
|
|
||||||
ExecutionControl() = delete;
|
ExecutionControl() = delete;
|
||||||
virtual ~ExecutionControl() = default;
|
virtual ~ExecutionControl();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace NebulOuS
|
} // namespace NebulOuS
|
||||||
|
@ -18,6 +18,7 @@ License: MPL2.0 (https://www.mozilla.org/en-US/MPL/2.0/)
|
|||||||
#include <ranges> // Container ranges
|
#include <ranges> // Container ranges
|
||||||
#include <algorithm> // Algorithms
|
#include <algorithm> // Algorithms
|
||||||
|
|
||||||
|
#include "Utility/ConsolePrint.hpp" // For logging
|
||||||
#include "Communication/AMQ/AMQEndpoint.hpp" // For Topic subscriptions
|
#include "Communication/AMQ/AMQEndpoint.hpp" // For Topic subscriptions
|
||||||
|
|
||||||
#include "MetricUpdater.hpp"
|
#include "MetricUpdater.hpp"
|
||||||
@ -41,36 +42,34 @@ namespace NebulOuS
|
|||||||
void MetricUpdater::AddMetricSubscription( const MetricTopic & TheMetrics,
|
void MetricUpdater::AddMetricSubscription( const MetricTopic & TheMetrics,
|
||||||
const Address OptimiserController )
|
const Address OptimiserController )
|
||||||
{
|
{
|
||||||
if( TheMetrics.is_object() &&
|
if( TheMetrics.is_object() &&
|
||||||
TheMetrics.at( NebulOuS::MetricList ).is_object() )
|
TheMetrics.at( NebulOuS::MetricList ).is_array() )
|
||||||
{
|
{
|
||||||
JSON MetricList = TheMetrics.at( NebulOuS::MetricList );
|
for (auto & MetricRecord : TheMetrics.at( NebulOuS::MetricList ) )
|
||||||
|
|
||||||
for( const JSON MetricDefinition : MetricList.items() )
|
|
||||||
{
|
|
||||||
auto [ MetricRecord, NewMetric ] = MetricValues.try_emplace(
|
|
||||||
MetricDefinition.at( NebulOuS::MetricName ), JSON() );
|
|
||||||
|
|
||||||
if( NewMetric )
|
|
||||||
Send( Theron::AMQ::NetworkLayer::TopicSubscription(
|
|
||||||
Theron::AMQ::NetworkLayer::TopicSubscription::Action::Subscription,
|
|
||||||
MetricRecord->first ),
|
|
||||||
Theron::AMQ::Network::GetAddress( Theron::Network::Layer::Session) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
std::source_location Location = std::source_location::current();
|
auto [ MetricRecordPointer, NewMetric ] = MetricValues.try_emplace(
|
||||||
std::ostringstream ErrorMessage;
|
MetricRecord.at( NebulOuS::MetricName ), JSON() );
|
||||||
|
|
||||||
ErrorMessage << "[" << Location.file_name() << " at line " << Location.line()
|
if( NewMetric )
|
||||||
<< "in function " << Location.function_name() <<"] "
|
Send( Theron::AMQ::NetworkLayer::TopicSubscription(
|
||||||
<< "The message to define a new metric subscription is given as "
|
Theron::AMQ::NetworkLayer::TopicSubscription::Action::Subscription,
|
||||||
<< std::endl << TheMetrics.dump(2) << std::endl
|
std::string( MetricValueRootString ) + MetricRecordPointer->first ),
|
||||||
<< "this is not as expected!";
|
Theron::AMQ::Network::GetAddress( Theron::Network::Layer::Session) );
|
||||||
|
|
||||||
throw std::invalid_argument( ErrorMessage.str() );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::source_location Location = std::source_location::current();
|
||||||
|
std::ostringstream ErrorMessage;
|
||||||
|
|
||||||
|
ErrorMessage << "[" << Location.file_name() << " at line " << Location.line()
|
||||||
|
<< " in function " << Location.function_name() <<"] "
|
||||||
|
<< "The message to define a new metric subscription is given as "
|
||||||
|
<< std::endl << TheMetrics.dump(2) << std::endl
|
||||||
|
<< "this is not as expected!";
|
||||||
|
|
||||||
|
throw std::invalid_argument( ErrorMessage.str() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The metric update value is received whenever any of subscribed forecasters
|
// The metric update value is received whenever any of subscribed forecasters
|
||||||
@ -102,9 +101,16 @@ void MetricUpdater::AddMetricSubscription( const MetricTopic & TheMetrics,
|
|||||||
void MetricUpdater::UpdateMetricValue(
|
void MetricUpdater::UpdateMetricValue(
|
||||||
const MetricValueUpdate & TheMetricValue, const Address TheMetricTopic)
|
const MetricValueUpdate & TheMetricValue, const Address TheMetricTopic)
|
||||||
{
|
{
|
||||||
|
Theron::ConsoleOutput Output;
|
||||||
|
|
||||||
|
Output << "Metric topic: " << TheMetricTopic.AsString() << std::endl;
|
||||||
|
|
||||||
Theron::AMQ::TopicName TheTopic
|
Theron::AMQ::TopicName TheTopic
|
||||||
= TheMetricTopic.AsString().erase( 0,
|
= TheMetricTopic.AsString().erase( 0,
|
||||||
NebulOuS::MetricValueRootString.size() );
|
NebulOuS::MetricValueRootString.size() );
|
||||||
|
|
||||||
|
Output << "The metric: " << TheTopic << " has new value "
|
||||||
|
<< TheMetricValue[ NebulOuS::ValueLabel ] << std::endl;
|
||||||
|
|
||||||
if( MetricValues.contains( TheTopic ) )
|
if( MetricValues.contains( TheTopic ) )
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ constexpr std::string_view TimePoint = "predictionTime";
|
|||||||
// defined next.
|
// defined next.
|
||||||
|
|
||||||
constexpr std::string_view MetricSubscriptions
|
constexpr std::string_view MetricSubscriptions
|
||||||
= "eu.nebulouscloud.monitoring.metric_lists";
|
= "eu.nebulouscloud.monitoring.metric_list";
|
||||||
|
|
||||||
// The JSON message attribute for the list of metrics is another JSON object
|
// The JSON message attribute for the list of metrics is another JSON object
|
||||||
// stored under the following key, see the Event type III defined in
|
// stored under the following key, see the Event type III defined in
|
||||||
@ -211,6 +211,10 @@ private:
|
|||||||
: JSONTopicMessage( Other )
|
: JSONTopicMessage( Other )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
// MetricTopic( const JSONTopicMessage & Other )
|
||||||
|
// : JSONTopicMessage( Other )
|
||||||
|
// {}
|
||||||
|
|
||||||
virtual ~MetricTopic() = default;
|
virtual ~MetricTopic() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,6 +54,17 @@ be extended with the AMPL execution file path, e.g.,
|
|||||||
|
|
||||||
export PATH=$PATH:/opt/AMPL
|
export PATH=$PATH:/opt/AMPL
|
||||||
|
|
||||||
|
The parameters to the application are used as described above, and typically the
|
||||||
|
endpoint is set to some unique identifier of the application for which this
|
||||||
|
solver is used, e.g.,
|
||||||
|
|
||||||
|
./SolverComponent --AMPLDir /opt/AMPL \
|
||||||
|
--Endpoint f81ee-b42a8-a13d56-e28ec9-2f5578 --ModelDir AMPLTest/
|
||||||
|
|
||||||
|
Debugging after a coredump
|
||||||
|
|
||||||
|
coredumpctl debug SolverComponent
|
||||||
|
|
||||||
Author and Copyright: Geir Horn, University of Oslo
|
Author and Copyright: Geir Horn, University of Oslo
|
||||||
Contact: Geir.Horn@mn.uio.no
|
Contact: Geir.Horn@mn.uio.no
|
||||||
License: MPL2.0 (https://www.mozilla.org/en-US/MPL/2.0/)
|
License: MPL2.0 (https://www.mozilla.org/en-US/MPL/2.0/)
|
||||||
@ -66,6 +77,7 @@ License: MPL2.0 (https://www.mozilla.org/en-US/MPL/2.0/)
|
|||||||
#include <sstream> // To format error messages
|
#include <sstream> // To format error messages
|
||||||
#include <stdexcept> // standard exceptions
|
#include <stdexcept> // standard exceptions
|
||||||
#include <filesystem> // Access to the file system
|
#include <filesystem> // Access to the file system
|
||||||
|
#include <map> // For extended AMQ properties
|
||||||
|
|
||||||
// Theron++ headers
|
// Theron++ headers
|
||||||
|
|
||||||
@ -78,7 +90,9 @@ License: MPL2.0 (https://www.mozilla.org/en-US/MPL/2.0/)
|
|||||||
|
|
||||||
// AMQ protocol related headers
|
// AMQ protocol related headers
|
||||||
|
|
||||||
|
#include "proton/symbol.hpp" // AMQ symbols
|
||||||
#include "proton/connection_options.hpp" // Options for the Broker
|
#include "proton/connection_options.hpp" // Options for the Broker
|
||||||
|
#include "proton/message.hpp" // AMQ messages definitions
|
||||||
#include "Communication/AMQ/AMQMessage.hpp" // The AMQP messages
|
#include "Communication/AMQ/AMQMessage.hpp" // The AMQP messages
|
||||||
#include "Communication/AMQ/AMQEndpoint.hpp" // The AMP endpoint
|
#include "Communication/AMQ/AMQEndpoint.hpp" // The AMP endpoint
|
||||||
#include "Communication/AMQ/AMQjson.hpp" // Transparent JSON-AMQP
|
#include "Communication/AMQ/AMQjson.hpp" // Transparent JSON-AMQP
|
||||||
@ -127,6 +141,8 @@ int main( int NumberOfCLIOptions, char ** CLIOptionStrings )
|
|||||||
cxxopts::value<unsigned int>()->default_value("5672") )
|
cxxopts::value<unsigned int>()->default_value("5672") )
|
||||||
("S,Solver", "Solver to use, devault Couenne",
|
("S,Solver", "Solver to use, devault Couenne",
|
||||||
cxxopts::value<std::string>()->default_value("couenne") )
|
cxxopts::value<std::string>()->default_value("couenne") )
|
||||||
|
("T,Tenant", "Tenant identifier for messages",
|
||||||
|
cxxopts::value<std::string>()->default_value("TheTenant"))
|
||||||
("U,User", "The user name used for the AMQ Broker connection",
|
("U,User", "The user name used for the AMQ Broker connection",
|
||||||
cxxopts::value<std::string>()->default_value("admin") )
|
cxxopts::value<std::string>()->default_value("admin") )
|
||||||
("Pw,Password", "The password for the AMQ Broker connection",
|
("Pw,Password", "The password for the AMQ Broker connection",
|
||||||
@ -180,29 +196,51 @@ int main( int NumberOfCLIOptions, char ** CLIOptionStrings )
|
|||||||
// The AMQ communication is managed by the standard communication actors of
|
// The AMQ communication is managed by the standard communication actors of
|
||||||
// the Theron++ Actor framewokr. Thus, it is just a matter of starting the
|
// the Theron++ Actor framewokr. Thus, it is just a matter of starting the
|
||||||
// endpoint actors with the given command line parameters.
|
// endpoint actors with the given command line parameters.
|
||||||
//
|
|
||||||
// The network endpoint takes the endpoint name as the first argument, then
|
// There are certain properties defined for the NebulOuS communication
|
||||||
// the URL for the broker and the port number. The user name and the password
|
// protocol where the endpoint name is taken as the application identifier
|
||||||
// are defined in the AMQ Qpid Proton connection options, and the values are
|
// and the tenant identifier and the protocol used. The same information
|
||||||
// therefore set for the connection options.
|
// has to be given as different maps for the connection options and for
|
||||||
|
// the message properties.
|
||||||
|
|
||||||
|
std::map< proton::symbol, proton::value > NebulOuSProperties{
|
||||||
|
{"x-tenant-id", CLIValues["Tenant"].as< std::string >() },
|
||||||
|
{"x-application-id", CLIValues["Endpoint"].as< std::string >()},
|
||||||
|
{"x-protocol", "AMQP"}
|
||||||
|
};
|
||||||
|
|
||||||
|
proton::message::property_map MessageProperties{
|
||||||
|
{"x-tenant-id", CLIValues["Tenant"].as< std::string >() },
|
||||||
|
{"x-application-id", CLIValues["Endpoint"].as< std::string >()},
|
||||||
|
{"x-protocol", "AMQP"}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The user name and the password are defined in the AMQ Qpid Proton
|
||||||
|
// connection options, and the values are therefore set for the connection
|
||||||
|
// options.
|
||||||
|
|
||||||
proton::connection_options AMQOptions;
|
proton::connection_options AMQOptions;
|
||||||
|
|
||||||
AMQOptions.user( CLIValues["User"].as< std::string >() );
|
AMQOptions.user( CLIValues["User"].as< std::string >() );
|
||||||
AMQOptions.password( CLIValues["Password"].as< std::string >() );
|
AMQOptions.password( CLIValues["Password"].as< std::string >() );
|
||||||
|
AMQOptions.properties( NebulOuSProperties );
|
||||||
// Then the network endpoint cna be constructed using the default names for
|
|
||||||
// the various network endpoint servers in order to pass the defined
|
// The network endpoint takes the endpoint name as the first argument, then
|
||||||
// connection options.
|
// the URL for the broker and the port number. Then the network endpoint can
|
||||||
|
// be constructed using the default names for the Session Layer and the
|
||||||
|
// Presentation layer servers, but calling the endpoint for "Solver" to make
|
||||||
|
// it more visible at the AMQ broker listing of subscribers. The endpoint
|
||||||
|
// will be a unique application identifier. The server names are followed
|
||||||
|
// by the defined connection options and the message options.
|
||||||
|
|
||||||
Theron::AMQ::NetworkEndpoint AMQNetWork(
|
Theron::AMQ::NetworkEndpoint AMQNetWork(
|
||||||
CLIValues["Endpoint"].as< std::string >(),
|
CLIValues["Endpoint"].as< std::string >(),
|
||||||
CLIValues["Broker"].as< std::string >(),
|
CLIValues["Broker"].as< std::string >(),
|
||||||
CLIValues["Port"].as< unsigned int >(),
|
CLIValues["Port"].as< unsigned int >(),
|
||||||
Theron::AMQ::Network::NetworkLayerLabel,
|
"Solver",
|
||||||
Theron::AMQ::Network::SessionLayerLabel,
|
Theron::AMQ::Network::SessionLayerLabel,
|
||||||
Theron::AMQ::Network::PresentationLayerLabel,
|
Theron::AMQ::Network::PresentationLayerLabel,
|
||||||
AMQOptions
|
AMQOptions, MessageProperties
|
||||||
);
|
);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
@ -97,11 +97,12 @@ class SolverManager
|
|||||||
{
|
{
|
||||||
// There is a topic name used to publish solutions found by the solvers. This
|
// There is a topic name used to publish solutions found by the solvers. This
|
||||||
// topic is given to the constructor and kept as a constant during the class
|
// topic is given to the constructor and kept as a constant during the class
|
||||||
// execution.
|
// execution. The same goes for the topic on which application execution
|
||||||
|
// contexts will arrive for processing.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const Theron::AMQ::TopicName SolutionReceiver;
|
const Theron::AMQ::TopicName SolutionReceiver, ContextTopic;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Solver management
|
// Solver management
|
||||||
@ -259,6 +260,7 @@ public:
|
|||||||
NetworkingActor( Actor::GetAddress().AsString() ),
|
NetworkingActor( Actor::GetAddress().AsString() ),
|
||||||
ExecutionControl( Actor::GetAddress().AsString() ),
|
ExecutionControl( Actor::GetAddress().AsString() ),
|
||||||
SolutionReceiver( SolutionTopic ),
|
SolutionReceiver( SolutionTopic ),
|
||||||
|
ContextTopic( ContextPublisherTopic ),
|
||||||
SolverPool(), ActiveSolvers(), PassiveSolvers(),
|
SolverPool(), ActiveSolvers(), PassiveSolvers(),
|
||||||
Contexts(), ContextExecutionQueue()
|
Contexts(), ContextExecutionQueue()
|
||||||
{
|
{
|
||||||
@ -322,6 +324,25 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The destructor closes all the open topics if the network is still open
|
||||||
|
// when the destructor is invoked.
|
||||||
|
|
||||||
|
virtual ~SolverManager( void )
|
||||||
|
{
|
||||||
|
if( HasNetwork() )
|
||||||
|
{
|
||||||
|
Send( Theron::AMQ::NetworkLayer::TopicSubscription(
|
||||||
|
Theron::AMQ::NetworkLayer::TopicSubscription::Action::ClosePublisher,
|
||||||
|
SolutionReceiver
|
||||||
|
), GetSessionLayerAddress() );
|
||||||
|
|
||||||
|
Send( Theron::AMQ::NetworkLayer::TopicSubscription(
|
||||||
|
Theron::AMQ::NetworkLayer::TopicSubscription::Action::CloseSubscription,
|
||||||
|
ContextTopic
|
||||||
|
), GetSessionLayerAddress() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace NebulOuS
|
} // namespace NebulOuS
|
||||||
|
4
makefile
4
makefile
@ -132,7 +132,7 @@ SOLVER_OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOLVER_SOURCE:.cpp=.o) )
|
|||||||
# component's objective file, they can be built by a general rule
|
# component's objective file, they can be built by a general rule
|
||||||
|
|
||||||
$(OBJECTS_DIR)/%.o : %.cpp
|
$(OBJECTS_DIR)/%.o : %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c $< -o $@ $(INCLUDE_DIRECTORIES)
|
$(CC) $(CXXFLAGS) -c $< -o $@ $(INCLUDE_DIRECTORIES)
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Solver component
|
# Solver component
|
||||||
@ -143,7 +143,7 @@ $(OBJECTS_DIR)/%.o : %.cpp
|
|||||||
# the object files or the solver actors.
|
# the object files or the solver actors.
|
||||||
|
|
||||||
SolverComponent: $(SOLVER_OBJECTS) $(THERON)/Theron++.a
|
SolverComponent: $(SOLVER_OBJECTS) $(THERON)/Theron++.a
|
||||||
$(CXX) -o SolverComponent $(CXXFLAGS) $(SOLVER_OBJECTS) $(LDFLAGS)
|
$(CC) -o SolverComponent $(CXXFLAGS) $(SOLVER_OBJECTS) $(LDFLAGS)
|
||||||
|
|
||||||
# There is also a standard target to clean the automatically generated build
|
# There is also a standard target to clean the automatically generated build
|
||||||
# files
|
# files
|
||||||
|
Loading…
Reference in New Issue
Block a user