1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-01-19 05:33:02 +00:00

Merge with next

This commit is contained in:
Javier Arribas 2021-01-27 10:21:16 +01:00
commit 5dd34b5e1b
50 changed files with 359 additions and 108 deletions

View File

@ -28,6 +28,15 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
- Improved handling of change in GNU Radio 3.9 FFT API. - Improved handling of change in GNU Radio 3.9 FFT API.
- Improved handling of the filesystem library. - Improved handling of the filesystem library.
- Do not apply clang-tidy fixes to protobuf-generated headers. - Do not apply clang-tidy fixes to protobuf-generated headers.
- Refactored private implementation of flow graph connection and disconnection
for improved source code readability.
### Improvements in Usability:
- Avoid segmentation faults in the flow graph connection and/or starting due to
some common inconsistencies in the configuration file.
- Provide hints to the user in case of failed flow graph connection due to
inconsistencies in the configuration file.
&nbsp; &nbsp;

View File

@ -59,7 +59,10 @@ bool Monitor_Pvt_Udp_Sink::write_monitor_pvt(const Monitor_Pvt* const monitor_pv
try try
{ {
socket.send(boost::asio::buffer(outbound_data)); if (socket.send(boost::asio::buffer(outbound_data)) == 0)
{
return false;
}
} }
catch (boost::system::system_error const& e) catch (boost::system::system_error const& e)
{ {

View File

@ -23,6 +23,7 @@
#include "telemetry_decoder_interface.h" #include "telemetry_decoder_interface.h"
#include "tracking_interface.h" #include "tracking_interface.h"
#include <glog/logging.h> #include <glog/logging.h>
#include <stdexcept> // for std::invalid_argument
#include <utility> // for std::move #include <utility> // for std::move
@ -113,6 +114,13 @@ void Channel::connect(gr::top_block_sptr top_block)
acq_->connect(top_block); acq_->connect(top_block);
} }
trk_->connect(top_block); trk_->connect(top_block);
if (trk_->item_size() == 0)
{
std::string msg = trk_->role() + ".item_type is not defined for implementation " + trk_->implementation() + '\n';
throw std::invalid_argument(msg);
}
nav_->connect(top_block); nav_->connect(top_block);
// Synchronous ports // Synchronous ports

View File

@ -17,6 +17,7 @@
#include "signal_conditioner.h" #include "signal_conditioner.h"
#include <glog/logging.h> #include <glog/logging.h>
#include <stdexcept>
#include <utility> #include <utility>
@ -40,10 +41,42 @@ void SignalConditioner::connect(gr::top_block_sptr top_block)
LOG(WARNING) << "Signal conditioner already connected internally"; LOG(WARNING) << "Signal conditioner already connected internally";
return; return;
} }
if (data_type_adapt_ == nullptr)
{
throw std::invalid_argument("DataTypeAdapter implementation not defined");
}
if (in_filt_ == nullptr)
{
throw std::invalid_argument("InputFilter implementation not defined");
}
if (res_ == nullptr)
{
throw std::invalid_argument("Resampler implementation not defined");
}
data_type_adapt_->connect(top_block); data_type_adapt_->connect(top_block);
in_filt_->connect(top_block); in_filt_->connect(top_block);
res_->connect(top_block); res_->connect(top_block);
if (in_filt_->item_size() == 0)
{
throw std::invalid_argument("itemsize mismatch: Invalid input/ouput data type configuration for the InputFilter");
}
const size_t data_type_adapter_output_size = data_type_adapt_->get_right_block()->output_signature()->sizeof_stream_item(0);
const size_t input_filter_input_size = in_filt_->get_left_block()->input_signature()->sizeof_stream_item(0);
const size_t input_filter_output_size = in_filt_->get_right_block()->output_signature()->sizeof_stream_item(0);
const size_t resampler_input_size = res_->get_left_block()->input_signature()->sizeof_stream_item(0);
if (data_type_adapter_output_size != input_filter_input_size)
{
throw std::invalid_argument("itemsize mismatch: Invalid input/ouput data type configuration for the DataTypeAdapter/InputFilter connection");
}
if (input_filter_output_size != resampler_input_size)
{
throw std::invalid_argument("itemsize mismatch: Invalid input/ouput data type configuration for the Input Filter/Resampler connection");
}
top_block->connect(data_type_adapt_->get_right_block(), 0, in_filt_->get_left_block(), 0); top_block->connect(data_type_adapt_->get_right_block(), 0, in_filt_->get_left_block(), 0);
DLOG(INFO) << "data_type_adapter -> input_filter"; DLOG(INFO) << "data_type_adapter -> input_filter";

View File

@ -43,7 +43,7 @@ BeamformerFilter::BeamformerFilter(
{ {
LOG(WARNING) << item_type_ LOG(WARNING) << item_type_
<< " unrecognized item type for beamformer"; << " unrecognized item type for beamformer";
item_size_ = sizeof(gr_complex); item_size_ = 0;
} }
if (dump_) if (dump_)
{ {

View File

@ -160,7 +160,7 @@ FreqXlatingFirFilter::FreqXlatingFirFilter(const ConfigurationInterface* configu
{ {
LOG(ERROR) << " Unknown input filter input/output item type conversion"; LOG(ERROR) << " Unknown input filter input/output item type conversion";
item_size = sizeof(gr_complex); // avoids uninitialization item_size = sizeof(gr_complex); // avoids uninitialization
input_size_ = sizeof(gr_complex); // avoids uninitialization input_size_ = 0; // notifies wrong configuration
} }
if (dump_) if (dump_)

View File

@ -51,7 +51,7 @@ NotchFilter::NotchFilter(const ConfigurationInterface* configuration, const std:
else else
{ {
LOG(WARNING) << item_type_ << " unrecognized item type for notch filter"; LOG(WARNING) << item_type_ << " unrecognized item type for notch filter";
item_size_ = sizeof(gr_complex); item_size_ = 0; // notify wrong configuration
} }
if (dump_) if (dump_)
{ {

View File

@ -58,7 +58,7 @@ NotchFilterLite::NotchFilterLite(const ConfigurationInterface* configuration, co
else else
{ {
LOG(WARNING) << item_type_ << " unrecognized item type for notch filter"; LOG(WARNING) << item_type_ << " unrecognized item type for notch filter";
item_size_ = sizeof(gr_complex); item_size_ = 0;
} }
if (dump_) if (dump_)
{ {

View File

@ -31,14 +31,12 @@ PulseBlankingFilter::PulseBlankingFilter(const ConfigurationInterface* configura
{ {
size_t item_size; size_t item_size;
xlat_ = false; xlat_ = false;
const std::string default_input_item_type("gr_complex"); const std::string default_item_type("gr_complex");
const std::string default_output_item_type("gr_complex");
const std::string default_dump_filename("../data/input_filter.dat"); const std::string default_dump_filename("../data/input_filter.dat");
DLOG(INFO) << "role " << role_; DLOG(INFO) << "role " << role_;
input_item_type_ = configuration->property(role_ + ".input_item_type", default_input_item_type); item_type_ = configuration->property(role_ + ".item_type", default_item_type);
output_item_type_ = configuration->property(role_ + ".output_item_type", default_output_item_type);
dump_ = configuration->property(role_ + ".dump", false); dump_ = configuration->property(role_ + ".dump", false);
dump_filename_ = configuration->property(role_ + ".dump_filename", default_dump_filename); dump_filename_ = configuration->property(role_ + ".dump_filename", default_dump_filename);
const float default_pfa_ = 0.04; const float default_pfa_ = 0.04;
@ -49,7 +47,7 @@ PulseBlankingFilter::PulseBlankingFilter(const ConfigurationInterface* configura
const int n_segments_est = configuration->property(role_ + ".segments_est", default_n_segments_est); const int n_segments_est = configuration->property(role_ + ".segments_est", default_n_segments_est);
const int default_n_segments_reset = 5000000; const int default_n_segments_reset = 5000000;
const int n_segments_reset = configuration->property(role_ + ".segments_reset", default_n_segments_reset); const int n_segments_reset = configuration->property(role_ + ".segments_reset", default_n_segments_reset);
if (input_item_type_ == "gr_complex") if (item_type_ == "gr_complex")
{ {
item_size = sizeof(gr_complex); // output item_size = sizeof(gr_complex); // output
input_size_ = sizeof(gr_complex); // input input_size_ = sizeof(gr_complex); // input
@ -57,9 +55,9 @@ PulseBlankingFilter::PulseBlankingFilter(const ConfigurationInterface* configura
} }
else else
{ {
LOG(ERROR) << " Unknown input filter input/output item type conversion"; LOG(ERROR) << "Unknown input filter item_types conversion";
item_size = sizeof(gr_complex); // avoids uninitialization item_size = sizeof(gr_complex); // avoids uninitialization
input_size_ = sizeof(gr_complex); // avoids uninitialization input_size_ = 0; // notify wrong configuration
} }
const double default_if = 0.0; const double default_if = 0.0;
const double if_aux = configuration->property(role_ + ".if", default_if); const double if_aux = configuration->property(role_ + ".if", default_if);
@ -95,7 +93,7 @@ PulseBlankingFilter::PulseBlankingFilter(const ConfigurationInterface* configura
void PulseBlankingFilter::connect(gr::top_block_sptr top_block) void PulseBlankingFilter::connect(gr::top_block_sptr top_block)
{ {
if (input_item_type_ == "gr_complex") if (item_type_ == "gr_complex")
{ {
if (dump_) if (dump_)
{ {
@ -116,7 +114,7 @@ void PulseBlankingFilter::connect(gr::top_block_sptr top_block)
void PulseBlankingFilter::disconnect(gr::top_block_sptr top_block) void PulseBlankingFilter::disconnect(gr::top_block_sptr top_block)
{ {
if (input_item_type_ == "gr_complex") if (item_type_ == "gr_complex")
{ {
if (dump_) if (dump_)
{ {
@ -136,7 +134,7 @@ void PulseBlankingFilter::disconnect(gr::top_block_sptr top_block)
gr::basic_block_sptr PulseBlankingFilter::get_left_block() gr::basic_block_sptr PulseBlankingFilter::get_left_block()
{ {
if (input_item_type_ == "gr_complex") if (item_type_ == "gr_complex")
{ {
if (xlat_) if (xlat_)
{ {
@ -151,7 +149,7 @@ gr::basic_block_sptr PulseBlankingFilter::get_left_block()
gr::basic_block_sptr PulseBlankingFilter::get_right_block() gr::basic_block_sptr PulseBlankingFilter::get_right_block()
{ {
if (input_item_type_ == "gr_complex") if (item_type_ == "gr_complex")
{ {
return pulse_blanking_cc_; return pulse_blanking_cc_;
} }

View File

@ -71,8 +71,7 @@ private:
gr::filter::freq_xlating_fir_filter_ccf::sptr freq_xlating_; gr::filter::freq_xlating_fir_filter_ccf::sptr freq_xlating_;
gr::blocks::file_sink::sptr file_sink_; gr::blocks::file_sink::sptr file_sink_;
std::string dump_filename_; std::string dump_filename_;
std::string input_item_type_; std::string item_type_;
std::string output_item_type_;
std::string role_; std::string role_;
size_t input_size_; size_t input_size_;
unsigned int in_streams_; unsigned int in_streams_;

View File

@ -32,16 +32,7 @@ Pass_Through::Pass_Through(const ConfigurationInterface* configuration, const st
out_streams_(out_streams) out_streams_(out_streams)
{ {
const std::string default_item_type("gr_complex"); const std::string default_item_type("gr_complex");
const std::string input_type = configuration->property(role + ".input_item_type", default_item_type); item_type_ = configuration->property(role + ".item_type", default_item_type);
const std::string output_type = configuration->property(role + ".output_item_type", default_item_type);
if (input_type != output_type)
{
LOG(WARNING) << "input_item_type and output_item_type are different in a Pass_Through implementation! Taking "
<< input_type
<< ", but item_size will supersede it.";
}
item_type_ = configuration->property(role + ".item_type", input_type);
inverted_spectrum = configuration->property(role + ".inverted_spectrum", false); inverted_spectrum = configuration->property(role + ".inverted_spectrum", false);
if (item_type_ == "float") if (item_type_ == "float")
@ -96,13 +87,11 @@ Pass_Through::Pass_Through(const ConfigurationInterface* configuration, const st
DLOG(INFO) << "kludge_copy(" << kludge_copy_->unique_id() << ")"; DLOG(INFO) << "kludge_copy(" << kludge_copy_->unique_id() << ")";
if (in_streams_ > 1) if (in_streams_ > 1)
{ {
LOG(ERROR) << "This implementation only supports one input stream"; LOG(ERROR) << "This implementation only supports one input stream but it is set to " << in_streams_;
LOG(ERROR) << in_streams_;
} }
if (out_streams_ > 1) if (out_streams_ > 1)
{ {
LOG(ERROR) << "This implementation only supports one output stream"; LOG(ERROR) << "This implementation only supports one output stream but it is set to " << out_streams_;
LOG(ERROR) << out_streams_;
} }
} }

View File

@ -92,6 +92,8 @@ TwoBitPackedFileSignalSource::TwoBitPackedFileSignalSource(
item_size_ = sizeof(char); item_size_ = sizeof(char);
} }
reverse_interleaving_ = false;
is_complex_ = true;
if (sample_type_ == "real") if (sample_type_ == "real")
{ {
is_complex_ = false; is_complex_ = false;
@ -99,7 +101,6 @@ TwoBitPackedFileSignalSource::TwoBitPackedFileSignalSource(
else if (sample_type_ == "iq") else if (sample_type_ == "iq")
{ {
is_complex_ = true; is_complex_ = true;
reverse_interleaving_ = false;
} }
else if (sample_type_ == "qi") else if (sample_type_ == "qi")
{ {

View File

@ -69,7 +69,7 @@ Fpga_dynamic_bit_selection::~Fpga_dynamic_bit_selection()
} }
void Fpga_dynamic_bit_selection::bit_selection(void) void Fpga_dynamic_bit_selection::bit_selection()
{ {
// estimated signal power corresponding to frequency band 1 // estimated signal power corresponding to frequency band 1
uint32_t rx_signal_power1 = d_map_base1[1]; uint32_t rx_signal_power1 = d_map_base1[1];

View File

@ -32,6 +32,9 @@ boost::system::error_code rtl_tcp_command(RTL_TCP_COMMAND id, unsigned param, bo
std::memcpy(&data[1], &nparam, sizeof(nparam)); std::memcpy(&data[1], &nparam, sizeof(nparam));
boost::system::error_code ec; boost::system::error_code ec;
socket.send(boost::asio::buffer(data), 0, ec); if (socket.send(boost::asio::buffer(data), 0, ec) == 0)
{
// 0 bytes sent
}
return ec; return ec;
} }

View File

@ -35,8 +35,8 @@ boost::system::error_code Rtl_Tcp_Dongle_Info::read(boost::asio::ip::tcp::socket
boost::system::error_code ec; boost::system::error_code ec;
unsigned char data[sizeof(char) * 4 + sizeof(uint32_t) * 2]; unsigned char data[sizeof(char) * 4 + sizeof(uint32_t) * 2];
socket.receive(boost::asio::buffer(data), 0, ec); size_t received_bits = socket.receive(boost::asio::buffer(data), 0, ec);
if (!ec) if (!ec && (received_bits > 0))
{ {
std::memcpy(magic_, data, 4); std::memcpy(magic_, data, 4);
@ -46,7 +46,7 @@ boost::system::error_code Rtl_Tcp_Dongle_Info::read(boost::asio::ip::tcp::socket
tuner_type_ = boost::asio::detail::socket_ops::network_to_host_long(type); tuner_type_ = boost::asio::detail::socket_ops::network_to_host_long(type);
uint32_t count; uint32_t count;
std ::memcpy(&count, &data[8], 4); std::memcpy(&count, &data[8], 4);
tuner_gain_count_ = boost::asio::detail::socket_ops::network_to_host_long(count); tuner_gain_count_ = boost::asio::detail::socket_ops::network_to_host_long(count);
} }

View File

@ -72,7 +72,7 @@ BeidouB1iDllPllTracking::BeidouB1iDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -64,7 +64,7 @@ BeidouB3iDllPllTracking::BeidouB3iDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -65,7 +65,7 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }

View File

@ -74,7 +74,7 @@ GalileoE1TcpConnectorTracking::GalileoE1TcpConnectorTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -65,7 +65,7 @@ GalileoE5aDllPllTracking::GalileoE5aDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -66,7 +66,7 @@ GalileoE5bDllPllTracking::GalileoE5bDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -61,7 +61,7 @@ GalileoE6DllPllTracking::GalileoE6DllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -95,7 +95,7 @@ GlonassL1CaDllPllCAidTracking::GlonassL1CaDllPllCAidTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type_ << " unknown tracking item type."; LOG(WARNING) << item_type_ << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -70,7 +70,7 @@ GlonassL1CaDllPllTracking::GlonassL1CaDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -93,7 +93,7 @@ GlonassL2CaDllPllCAidTracking::GlonassL2CaDllPllCAidTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type_ << " unknown tracking item type."; LOG(WARNING) << item_type_ << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -68,7 +68,7 @@ GlonassL2CaDllPllTracking::GlonassL2CaDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -73,7 +73,7 @@ GpsL1CaDllPllTracking::GpsL1CaDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -72,7 +72,7 @@ GpsL1CaDllPllTrackingGPU::GpsL1CaDllPllTrackingGPU(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -81,7 +81,7 @@ GpsL1CaKfTracking::GpsL1CaKfTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -60,7 +60,7 @@ GpsL1CaTcpConnectorTracking::GpsL1CaTcpConnectorTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << item_type << " unknown tracking item type."; LOG(WARNING) << item_type << " unknown tracking item type.";
} }

View File

@ -62,7 +62,7 @@ GpsL2MDllPllTracking::GpsL2MDllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -65,7 +65,7 @@ GpsL5DllPllTracking::GpsL5DllPllTracking(
} }
else else
{ {
item_size_ = sizeof(gr_complex); item_size_ = 0;
LOG(WARNING) << trk_params.item_type << " unknown tracking item type."; LOG(WARNING) << trk_params.item_type << " unknown tracking item type.";
} }
channel_ = 0; channel_ = 0;

View File

@ -1297,7 +1297,7 @@ int32_t dll_pll_veml_tracking_fpga::save_matfile() const
} }
void dll_pll_veml_tracking_fpga::set_channel(uint32_t channel, std::string device_io_name) void dll_pll_veml_tracking_fpga::set_channel(uint32_t channel, const std::string &device_io_name)
{ {
gr::thread::scoped_lock l(d_setlock); gr::thread::scoped_lock l(d_setlock);

View File

@ -66,7 +66,7 @@ public:
/*! /*!
* \brief Set the channel number and configure some multicorrelator parameters * \brief Set the channel number and configure some multicorrelator parameters
*/ */
void set_channel(uint32_t channel, std::string device_io_name); void set_channel(uint32_t channel, const std::string &device_io_name);
/*! /*!
* \brief This function is used with two purposes: * \brief This function is used with two purposes:

View File

@ -192,7 +192,7 @@ bool Fpga_Multicorrelator_8sc::free()
} }
void Fpga_Multicorrelator_8sc::open_channel(std::string device_io_name, uint32_t channel) void Fpga_Multicorrelator_8sc::open_channel(const std::string &device_io_name, uint32_t channel)
{ {
std::cout << "trk device_io_name = " << device_io_name << '\n'; std::cout << "trk device_io_name = " << device_io_name << '\n';

View File

@ -91,7 +91,7 @@ public:
/*! /*!
* \brief Open the FPGA device driver * \brief Open the FPGA device driver
*/ */
void open_channel(std::string device_io_name, uint32_t channel); void open_channel(const std::string &device_io_name, uint32_t channel);
/*! /*!
* \brief Set the initial sample number where the tracking process begins * \brief Set the initial sample number where the tracking process begins

View File

@ -66,10 +66,16 @@ void Tcp_Communication::send_receive_tcp_packet_galileo_e1(boost::array<float, N
try try
{ {
// Send a TCP packet // Send a TCP packet
tcp_socket_.write_some(boost::asio::buffer(buf)); if (tcp_socket_.write_some(boost::asio::buffer(buf)) == 0)
{
std::cerr << "Tcp_Communication: Error sending TCP packet\n";
}
// Read the received TCP packet // Read the received TCP packet
tcp_socket_.read_some(boost::asio::buffer(readbuf)); if (tcp_socket_.read_some(boost::asio::buffer(readbuf)) == 0)
{
std::cerr << "Tcp_Communication: Error reading TCP packet\n";
}
//! Control. The GNSS-SDR program ends if an error in a TCP packet is detected. //! Control. The GNSS-SDR program ends if an error in a TCP packet is detected.
if (d_control_id_ != readbuf.data()[0]) if (d_control_id_ != readbuf.data()[0])
@ -100,10 +106,16 @@ void Tcp_Communication::send_receive_tcp_packet_gps_l1_ca(boost::array<float, NU
try try
{ {
// Send a TCP packet // Send a TCP packet
tcp_socket_.write_some(boost::asio::buffer(buf)); if (tcp_socket_.write_some(boost::asio::buffer(buf)) == 0)
{
std::cerr << "Tcp_Communication error sending TCP packet\n";
}
// Read the received TCP packet // Read the received TCP packet
tcp_socket_.read_some(boost::asio::buffer(readbuf)); if (tcp_socket_.read_some(boost::asio::buffer(readbuf)) == 0)
{
std::cerr << "Tcp_Communication error: reading 0 bytes from TCP packet\n";
}
//! Control. The GNSS-SDR program ends if an error in a TCP packet is detected. //! Control. The GNSS-SDR program ends if an error in a TCP packet is detected.
if (d_control_id_ != readbuf.data()[0]) if (d_control_id_ != readbuf.data()[0])
@ -122,6 +134,10 @@ void Tcp_Communication::send_receive_tcp_packet_gps_l1_ca(boost::array<float, NU
std::cerr << "Exception: " << e.what() << ". Please press Ctrl+C to end the program.\n"; std::cerr << "Exception: " << e.what() << ". Please press Ctrl+C to end the program.\n";
std::cin >> controlc; std::cin >> controlc;
} }
catch (...)
{
std::cerr << "Exception reading TCP data\n";
}
} }

View File

@ -81,3 +81,23 @@ int INIReader::ValueHandler(void* user, const char* section, const char* name,
reader->_values[MakeKey(section, name)] = value; reader->_values[MakeKey(section, name)] = value;
return 1; return 1;
} }
bool INIReader::HasSection(const std::string& section) const
{
const std::string key = MakeKey(section, "");
auto pos = _values.lower_bound(key);
if (pos == _values.end())
{
return false;
}
// Does the key at the lower_bound pos start with "section"?
return pos->first.compare(0, key.length(), key) == 0;
}
bool INIReader::HasValue(const std::string& section, const std::string& name) const
{
std::string key = MakeKey(section, name);
return _values.count(key);
}

View File

@ -58,6 +58,12 @@ public:
//! Get an integer (long) value from INI file, returning default_value if not found. //! Get an integer (long) value from INI file, returning default_value if not found.
int64_t GetInteger(const std::string& section, const std::string& name, int64_t default_value); int64_t GetInteger(const std::string& section, const std::string& name, int64_t default_value);
//! Return true if the given section exists (section must contain at least one name=value pair).
bool HasSection(const std::string& section) const;
//! Return true if a value exists with the given section and field names.
bool HasValue(const std::string& section, const std::string& name) const;
private: private:
static std::string MakeKey(const std::string& section, const std::string& name); static std::string MakeKey(const std::string& section, const std::string& name);
static int ValueHandler(void* user, const char* section, const char* name, static int ValueHandler(void* user, const char* section, const char* name,

View File

@ -32,7 +32,10 @@ int32_t get_uio_num(std::string uio_name)
// search first digit // search first digit
for (; i < uio_name.length(); i++) for (; i < uio_name.length(); i++)
{ {
if (isdigit(uio_name[i])) break; if (isdigit(uio_name[i]))
{
break;
}
} }
// remove the first chars, which aren't digits // remove the first chars, which aren't digits
@ -79,8 +82,8 @@ int my_strverscmp(const char *s1, const char *s2)
const int8_t CMP = 2; const int8_t CMP = 2;
const int8_t LEN = 3; const int8_t LEN = 3;
const unsigned char *p1 = (const unsigned char *)s1; const auto *p1 = reinterpret_cast<const unsigned char *>(s1);
const unsigned char *p2 = (const unsigned char *)s2; const auto *p2 = reinterpret_cast<const unsigned char *>(s2);
/* Symbol(s) 0 [1-9] others /* Symbol(s) 0 [1-9] others
Transition (10) 0 (01) d (00) x */ Transition (10) 0 (01) d (00) x */
static const uint8_t next_state[] = static const uint8_t next_state[] =
@ -137,7 +140,7 @@ int my_strverscmp(const char *s1, const char *s2)
} }
bool sort_directories(fs::directory_entry a, fs::directory_entry b) bool sort_directories(const fs::directory_entry &a, const fs::directory_entry &b)
{ {
int cmp = my_strverscmp(a.path().string().c_str(), b.path().string().c_str()); int cmp = my_strverscmp(a.path().string().c_str(), b.path().string().c_str());
return (cmp < 0); return (cmp < 0);
@ -166,7 +169,7 @@ int32_t find_uio_num(const std::string &device_name, uint32_t device_num)
{ {
std::string nametemp; std::string nametemp;
get_uio_name(uio_num, nametemp); get_uio_name(uio_num, nametemp);
if (device_name.compare(nametemp) == 0) if (device_name == nametemp)
{ {
if (uio_count == device_num) if (uio_count == device_num)
{ {

View File

@ -57,10 +57,14 @@ bool Gnss_Synchro_Udp_Sink::write_gnss_synchro(const std::vector<Gnss_Synchro>&
try try
{ {
socket.send(boost::asio::buffer(outbound_data)); if (socket.send(boost::asio::buffer(outbound_data)) == 0)
{
std::cerr << "Gnss_Synchro_Udp_Sink sent 0 bytes\n";
}
} }
catch (boost::system::system_error const& e) catch (boost::system::system_error const& e)
{ {
std::cerr << e.what() << '\n';
return false; return false;
} }
} }

View File

@ -83,6 +83,41 @@ ControlThread::ControlThread()
{ {
configuration_ = std::make_shared<FileConfiguration>(FLAGS_c); configuration_ = std::make_shared<FileConfiguration>(FLAGS_c);
} }
// Basic configuration checks
auto aux = std::dynamic_pointer_cast<FileConfiguration>(configuration_);
conf_file_has_section_ = aux->has_section();
conf_file_has_mandatory_globals_ = (configuration_->property("GNSS-SDR.internal_fs_sps", 0) == 0 ? false : true);
const std::string empty_implementation;
std::string src_impl = configuration_->property("SignalSource.implementation", empty_implementation);
int src_count = configuration_->property("Receiver.sources_count", 1);
if (src_impl.empty() && (src_count != 1))
{
int num_src = 0;
for (int i = 0; i < src_count; i++)
{
std::string src_impl_multiple = configuration_->property("SignalSource" + std::to_string(i) + ".implementation", empty_implementation);
if (!src_impl_multiple.empty())
{
num_src++;
}
}
if (num_src != src_count)
{
src_impl = std::string("");
}
}
conf_has_signal_sources_ = !src_impl.empty();
std::string pvt_impl = configuration_->property("PVT.implementation", empty_implementation);
conf_has_pvt_ = !pvt_impl.empty();
std::string obs_impl = configuration_->property("Observables.implementation", empty_implementation);
conf_has_observables_ = !obs_impl.empty();
well_formatted_configuration_ = conf_file_has_section_ && conf_file_has_mandatory_globals_ && conf_has_signal_sources_ && conf_has_observables_ && conf_has_pvt_;
restart_ = false; restart_ = false;
init(); init();
} }
@ -91,6 +126,12 @@ ControlThread::ControlThread()
ControlThread::ControlThread(std::shared_ptr<ConfigurationInterface> configuration) ControlThread::ControlThread(std::shared_ptr<ConfigurationInterface> configuration)
{ {
configuration_ = std::move(configuration); configuration_ = std::move(configuration);
conf_file_has_section_ = true;
conf_file_has_mandatory_globals_ = true;
conf_has_signal_sources_ = true;
conf_has_observables_ = true;
conf_has_pvt_ = true;
well_formatted_configuration_ = true;
restart_ = false; restart_ = false;
init(); init();
} }
@ -104,6 +145,8 @@ void ControlThread::init()
// Instantiates a control queue, a GNSS flowgraph, and a control message factory // Instantiates a control queue, a GNSS flowgraph, and a control message factory
control_queue_ = std::make_shared<Concurrent_Queue<pmt::pmt_t>>(); control_queue_ = std::make_shared<Concurrent_Queue<pmt::pmt_t>>();
cmd_interface_.set_msg_queue(control_queue_); // set also the queue pointer for the telecommand thread cmd_interface_.set_msg_queue(control_queue_); // set also the queue pointer for the telecommand thread
if (well_formatted_configuration_)
{
try try
{ {
flowgraph_ = std::make_shared<GNSSFlowgraph>(configuration_, control_queue_); flowgraph_ = std::make_shared<GNSSFlowgraph>(configuration_, control_queue_);
@ -112,6 +155,12 @@ void ControlThread::init()
{ {
std::cout << "Caught bad lexical cast with error " << e.what() << '\n'; std::cout << "Caught bad lexical cast with error " << e.what() << '\n';
} }
}
else
{
flowgraph_ = nullptr;
}
stop_ = false; stop_ = false;
processed_control_messages_ = 0; processed_control_messages_ = 0;
applied_actions_ = 0; applied_actions_ = 0;
@ -285,6 +334,11 @@ void ControlThread::event_dispatcher(bool &valid_event, pmt::pmt_t &msg)
int ControlThread::run() int ControlThread::run()
{ {
// Connect the flowgraph // Connect the flowgraph
if (!flowgraph_)
{
print_help_at_exit();
return 0;
}
try try
{ {
flowgraph_->connect(); flowgraph_->connect();
@ -300,7 +354,6 @@ int ControlThread::run()
} }
else else
{ {
LOG(ERROR) << "Unable to connect flowgraph";
return 0; return 0;
} }
// Start the flowgraph // Start the flowgraph
@ -311,7 +364,6 @@ int ControlThread::run()
} }
else else
{ {
LOG(ERROR) << "Unable to start flowgraph";
return 0; return 0;
} }
@ -1147,3 +1199,37 @@ void ControlThread::keyboard_listener()
} }
} }
} }
void ControlThread::print_help_at_exit() const
{
std::cerr << "Error: the configuration file is not well formatted\n";
if (!conf_file_has_section_)
{
std::cerr << " * The section label has not been found if the configuration file\n"
<< " Please add the [GNSS-SDR] label at the top of your configuration file\n"
<< " A configuration example is available at https://gnss-sdr.org/my-first-fix/\n";
return;
}
if (!conf_file_has_mandatory_globals_)
{
std::cerr << " * Have you forgotten to set the mandatory global parameter GNSS-SDR.internal_fs_sps in your conf file?\n"
<< " Documentation about this parameter at https://gnss-sdr.org/docs/sp-blocks/global-parameters/\n"
<< " A configuration example is available at https://gnss-sdr.org/my-first-fix/\n";
}
if (!conf_has_signal_sources_)
{
std::cerr << " * The configuration file must define at least one SignalSource.implementation\n"
<< " Documentation of SignalSource block implementations at https://gnss-sdr.org/docs/sp-blocks/signal-source/\n";
}
if (!conf_has_observables_)
{
std::cerr << " * The configuration file must define an Observables.implementation\n"
<< " Documentation of the Observables block at https://gnss-sdr.org/docs/sp-blocks/observables/\n";
}
if (!conf_has_pvt_)
{
std::cerr << " * The configuration file must define a PVT.implementation\n"
<< " Documentation of the PVT block at https://gnss-sdr.org/docs/sp-blocks/pvt/\n";
}
}

View File

@ -153,6 +153,7 @@ private:
void telecommand_listener(); void telecommand_listener();
void keyboard_listener(); void keyboard_listener();
void sysv_queue_listener(); void sysv_queue_listener();
void print_help_at_exit() const;
// default filename for assistance data // default filename for assistance data
const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml"; const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml";
@ -203,6 +204,12 @@ private:
unsigned int applied_actions_; unsigned int applied_actions_;
int msqid_; int msqid_;
bool well_formatted_configuration_;
bool conf_file_has_section_;
bool conf_file_has_mandatory_globals_;
bool conf_has_signal_sources_;
bool conf_has_observables_;
bool conf_has_pvt_;
bool receiver_on_standby_; bool receiver_on_standby_;
bool stop_; bool stop_;
bool restart_; bool restart_;

View File

@ -60,6 +60,12 @@ void FileConfiguration::init()
} }
bool FileConfiguration::has_section() const
{
return ini_reader_->HasSection("GNSS-SDR");
}
std::string FileConfiguration::property(std::string property_name, std::string default_value) const std::string FileConfiguration::property(std::string property_name, std::string default_value) const
{ {
if (overrided_->is_present(property_name)) if (overrided_->is_present(property_name))

View File

@ -63,6 +63,7 @@ public:
double property(std::string property_name, double default_value) const override; double property(std::string property_name, double default_value) const override;
void set_property(std::string property_name, std::string value) override; void set_property(std::string property_name, std::string value) override;
bool is_present(const std::string& property_name) const; bool is_present(const std::string& property_name) const;
bool has_section() const;
private: private:
void init(); void init();

View File

@ -375,6 +375,7 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel(
if (acq_item_type != trk_item_type) if (acq_item_type != trk_item_type)
{ {
LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!"; LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!";
return nullptr;
} }
LOG(INFO) << "Instantiating Channel " << channel LOG(INFO) << "Instantiating Channel " << channel
@ -389,6 +390,16 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel(
std::unique_ptr<TrackingInterface> trk_ = GetTrkBlock(configuration, "Tracking_" + signal + appendix2, 1, 1); std::unique_ptr<TrackingInterface> trk_ = GetTrkBlock(configuration, "Tracking_" + signal + appendix2, 1, 1);
std::unique_ptr<TelemetryDecoderInterface> tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_" + signal + appendix3, 1, 1); std::unique_ptr<TelemetryDecoderInterface> tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_" + signal + appendix3, 1, 1);
if (acq_ == nullptr or trk_ == nullptr or tlm_ == nullptr)
{
return nullptr;
}
if (trk_->item_size() == 0)
{
LOG(ERROR) << trk_->role() << ".item_type=" << acq_item_type << " is not defined for implementation " << trk_->implementation();
return nullptr;
}
std::unique_ptr<GNSSBlockInterface> channel_ = std::make_unique<Channel>(configuration, channel, std::unique_ptr<GNSSBlockInterface> channel_ = std::make_unique<Channel>(configuration, channel,
std::move(acq_), std::move(acq_),
std::move(trk_), std::move(trk_),
@ -1327,8 +1338,7 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
else else
{ {
// Log fatal. This causes execution to stop. LOG(ERROR) << role << " block: Undefined implementation " << implementation;
LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block";
} }
return block; return block;
} }
@ -1522,8 +1532,7 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
else else
{ {
// Log fatal. This causes execution to stop. LOG(ERROR) << role << " block: Undefined implementation " << implementation;
LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block";
} }
return block; return block;
} }
@ -1684,8 +1693,7 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
#endif #endif
else else
{ {
// Log fatal. This causes execution to stop. LOG(ERROR) << role << " block: Undefined implementation " << implementation;
LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block";
} }
return block; return block;
} }
@ -1777,8 +1785,7 @@ std::unique_ptr<TelemetryDecoderInterface> GNSSBlockFactory::GetTlmBlock(
else else
{ {
// Log fatal. This causes execution to stop. LOG(ERROR) << role << " block: Undefined implementation " << implementation;
LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block";
} }
return block; return block;
} }

View File

@ -688,16 +688,6 @@ void GNSSFlowgraph::connect()
{ {
top_block_->connect(observables_->get_right_block(), i, pvt_->get_left_block(), i); top_block_->connect(observables_->get_right_block(), i, pvt_->get_left_block(), i);
top_block_->msg_connect(channels_.at(i)->get_right_block(), pmt::mp("telemetry"), pvt_->get_left_block(), pmt::mp("telemetry")); top_block_->msg_connect(channels_.at(i)->get_right_block(), pmt::mp("telemetry"), pvt_->get_left_block(), pmt::mp("telemetry"));
//experimental VTL
//TODO: It is currently implemented only in dll_pll_veml_tracking, other configs will fail!
try
{
top_block_->msg_connect(pvt_->get_left_block(), pmt::mp("pvt_to_trk"), channels_.at(i)->get_left_block_trk(), pmt::mp("pvt_to_trk"));
}
catch (std::exception& ex)
{
LOG(WARNING) << "pvt_to_trk message not implemented in " << channels_.at(i)->implementation();
}
} }
top_block_->msg_connect(observables_->get_right_block(), pmt::mp("status"), channels_status_, pmt::mp("status")); top_block_->msg_connect(observables_->get_right_block(), pmt::mp("status"), channels_status_, pmt::mp("status"));

View File

@ -153,7 +153,7 @@ public:
*/ */
void priorize_satellites(const std::vector<std::pair<int, Gnss_Satellite>>& visible_satellites); void priorize_satellites(const std::vector<std::pair<int, Gnss_Satellite>>& visible_satellites);
#ifdef ENABLE_FPGA #if ENABLE_FPGA
void start_acquisition_helper(); void start_acquisition_helper();
void perform_hw_reset(); void perform_hw_reset();
@ -161,6 +161,49 @@ public:
private: private:
void init(); // Populates the SV PRN list available for acquisition and tracking void init(); // Populates the SV PRN list available for acquisition and tracking
int connect_desktop_flowgraph();
int connect_signal_sources();
int connect_signal_conditioners();
int connect_channels();
int connect_observables();
int connect_pvt();
int connect_sample_counter();
int connect_signal_sources_to_signal_conditioners();
int connect_signal_conditioners_to_channels();
int connect_channels_to_observables();
int connect_observables_to_pvt();
int connect_monitors();
int connect_gnss_synchro_monitor();
int connect_acquisition_monitor();
int connect_tracking_monitor();
int disconnect_desktop_flowgraph();
int disconnect_signal_sources();
int disconnect_signal_conditioners();
int disconnect_channels();
int disconnect_observables();
int disconnect_pvt();
int disconnect_sample_counter();
int disconnect_signal_sources_from_signal_conditioners();
int disconnect_signal_conditioners_from_channels();
int disconnect_channels_from_observables();
int disconnect_observables_from_pvt();
int disconnect_monitors();
#if ENABLE_FPGA
int connect_fpga_flowgraph();
int disconnect_fpga_flowgraph();
int connect_fpga_sample_counter();
int disconnect_fpga_sample_counter();
#endif
void assign_channels();
void check_signal_conditioners();
void set_signals_list(); void set_signals_list();
void set_channels_state(); // Initializes the channels state (start acquisition or keep standby) void set_channels_state(); // Initializes the channels state (start acquisition or keep standby)
// using the configuration parameters (number of channels and max channels in acquisition) // using the configuration parameters (number of channels and max channels in acquisition)
@ -173,11 +216,14 @@ private:
void push_back_signal(const Gnss_Signal& gs); void push_back_signal(const Gnss_Signal& gs);
void remove_signal(const Gnss_Signal& gs); void remove_signal(const Gnss_Signal& gs);
void print_help();
void check_desktop_conf_in_fpga_env();
double project_doppler(const std::string& searched_signal, double primary_freq_doppler_hz); double project_doppler(const std::string& searched_signal, double primary_freq_doppler_hz);
bool is_multiband() const; bool is_multiband() const;
std::vector<std::string> split_string(const std::string& s, char delim); std::vector<std::string> split_string(const std::string& s, char delim);
std::vector<bool> signal_conditioner_connected_;
gr::top_block_sptr top_block_; gr::top_block_sptr top_block_;
@ -235,6 +281,7 @@ private:
std::map<std::string, StringValue> mapStringValues_; std::map<std::string, StringValue> mapStringValues_;
std::string config_file_; std::string config_file_;
std::string help_hint_;
std::mutex signal_list_mutex_; std::mutex signal_list_mutex_;

View File

@ -326,7 +326,7 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
acceptor.accept(socket, not_throw); acceptor.accept(socket, not_throw);
if (not_throw) if (not_throw)
{ {
std::cout << "TcpCmdInterface: Error when binding the port in the socket\n"; std::cerr << "TcpCmdInterface: Error when binding the port in the socket\n";
continue; continue;
} }
@ -336,7 +336,10 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
{ {
std::string response; std::string response;
boost::asio::streambuf b; boost::asio::streambuf b;
boost::asio::read_until(socket, b, '\n', error); if (boost::asio::read_until(socket, b, '\n', error) == 0)
{
std::cerr << "TcpCmdInterface: Error reading messages: " << error.message() << '\n';
}
std::istream is(&b); std::istream is(&b);
std::string line; std::string line;
std::getline(is, line); std::getline(is, line);
@ -352,7 +355,10 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
{ {
error = boost::asio::error::eof; error = boost::asio::error::eof;
// send cmd response // send cmd response
socket.write_some(boost::asio::buffer("OK\n"), not_throw); if (socket.write_some(boost::asio::buffer("OK\n"), not_throw) == 0)
{
std::cerr << "Error: 0 bytes sent in cmd response\n";
}
} }
else else
{ {
@ -374,10 +380,13 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
} }
// send cmd response // send cmd response
socket.write_some(boost::asio::buffer(response), not_throw); if (socket.write_some(boost::asio::buffer(response), not_throw) == 0)
{
std::cerr << "Error: 0 bytes sent in cmd response\n";
}
if (not_throw) if (not_throw)
{ {
std::cout << "Error sending(" << not_throw.value() << "): " << not_throw.message() << '\n'; std::cerr << "Error sending(" << not_throw.value() << "): " << not_throw.message() << '\n';
break; break;
} }
} }
@ -385,11 +394,11 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
if (error == boost::asio::error::eof) if (error == boost::asio::error::eof)
{ {
std::cout << "TcpCmdInterface: EOF detected\n"; std::cerr << "TcpCmdInterface: EOF detected\n";
} }
else else
{ {
std::cout << "TcpCmdInterface unexpected error: " << error << '\n'; std::cerr << "TcpCmdInterface unexpected error: " << error << '\n';
} }
// Close socket // Close socket
@ -397,16 +406,16 @@ void TcpCmdInterface::run_cmd_server(int tcp_port)
} }
catch (const boost::exception &e) catch (const boost::exception &e)
{ {
std::cout << "TcpCmdInterface: Boost exception\n"; std::cerr << "TcpCmdInterface: Boost exception\n";
} }
catch (const std::exception &ex) catch (const std::exception &ex)
{ {
std::cout << "TcpCmdInterface: Exception " << ex.what() << '\n'; std::cerr << "TcpCmdInterface: Exception " << ex.what() << '\n';
} }
} }
} }
catch (const boost::exception &e) catch (const boost::exception &e)
{ {
std::cout << "TCP Command Interface exception: address already in use\n"; std::cerr << "TCP Command Interface exception: address already in use\n";
} }
} }

View File

@ -63,9 +63,15 @@ if(NOT GOOGLETEST_FOUND)
${CMAKE_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gtest_maind${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gtest_maind${CMAKE_STATIC_LIBRARY_SUFFIX}
) )
endif() endif()
set(GOOGLETEST_GIT_TAG "v1.10.x")
if(CMAKE_VERSION VERSION_GREATER 3.18.99)
# workaround to avoid warning about deprecated CMakeLists.txt with CMake >= 3.19
# Remove after a stable release of Googletest including this fix
set(GOOGLETEST_GIT_TAG "d128fc8252d53baad6ea456fa08cbf9028d255f4")
endif()
ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION} ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
GIT_REPOSITORY https://github.com/google/googletest GIT_REPOSITORY https://github.com/google/googletest
GIT_TAG v1.10.x GIT_TAG ${GOOGLETEST_GIT_TAG}
SOURCE_DIR ${CMAKE_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} SOURCE_DIR ${CMAKE_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
BINARY_DIR ${CMAKE_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} BINARY_DIR ${CMAKE_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
CMAKE_ARGS ${GTEST_COMPILER} CMAKE_ARGS ${GTEST_COMPILER}