Skip to content

Commit

Permalink
Merge pull request #3209 from eseiler/infra/ci_libc++
Browse files Browse the repository at this point in the history
[FEATURE] libc++ support
  • Loading branch information
eseiler authored Nov 13, 2023
2 parents 1b0b55f + e2dd179 commit fc8f4f7
Show file tree
Hide file tree
Showing 20 changed files with 120 additions and 47 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ jobs:
fail-fast: true
matrix:
include:
- name: "clang17 libc++"
compiler: "clang-17"
build: unit
build_type: Release
cxx_flags: "-stdlib=libc++"

- name: "clang17"
compiler: "clang-17"
build: unit
Expand Down
3 changes: 3 additions & 0 deletions include/seqan3/core/debug_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
//!\cond
namespace std
{
namespace
{
extern ostream cerr;
}
} // namespace std
//!\endcond

Expand Down
5 changes: 5 additions & 0 deletions include/seqan3/core/debug_stream/debug_stream_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,17 @@ class debug_stream_type
stream->unsetf(flag);
}

// fmtflags is an enum in libstdc++ and an unsigned in libc++
#ifdef _LIBCPP_VERSION
static_assert(std::same_as<fmtflags, unsigned>);
#else
//!\copybrief setf()
debug_stream_type & operator<<(fmtflags const flag)
{
setf(flag);
return *this;
}
#endif
//!\}

/*!\name Format flags (seqan3::fmtflags2)
Expand Down
4 changes: 2 additions & 2 deletions include/seqan3/io/sam_file/format_bam.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ format_bam::read_alignment_record(stream_type & stream,
ref_id = core.refID; // field::ref_id
}

flag = core.flag; // field::flag
mapq = core.mapq; // field::mapq
flag = core.flag; // field::flag
mapq = static_cast<uint8_t>(core.mapq); // field::mapq

if (core.pos > -1) // [[likely]]
ref_offset = core.pos; // field::ref_offset
Expand Down
16 changes: 8 additions & 8 deletions include/seqan3/io/sequence_file/format_embl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ class format_embl
id_type & id,
qual_type & SEQAN3_DOXYGEN_ONLY(qualities))
{
// Store current position in buffer
// Must happen before constructing the view.
// With libc++, tellg invalidates the I/O buffer.
position_buffer = stream.tellg();

auto stream_view = detail::istreambuf(stream);
auto stream_it = std::ranges::begin(stream_view);

// Store current position in buffer.
position_buffer = stream.tellg();

std::string idbuffer;
std::ranges::copy(stream_view | detail::take_until_or_throw(is_cntrl || is_blank),
std::back_inserter(idbuffer));
Expand Down Expand Up @@ -195,12 +197,10 @@ class format_embl
}
else
{
detail::consume(stream_view | detail::take_until(is_end));
detail::consume(stream_view | detail::take_until_or_throw(is_end)); // consume until "//"
}
//Jump over // and cntrl
++stream_it;
++stream_it;
++stream_it;

std::ranges::advance(stream_it, 3u, std::ranges::end(stream_view)); // Skip `//` and potentially '\n'
}

//!\copydoc sequence_file_output_format::write_sequence_record
Expand Down
6 changes: 4 additions & 2 deletions include/seqan3/io/sequence_file/format_fasta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,13 @@ class format_fasta
id_type & id,
qual_type & SEQAN3_DOXYGEN_ONLY(qualities))
{
auto stream_view = detail::istreambuf(stream);

// Store current position in buffer
// Must happen before constructing the view.
// With libc++, tellg invalidates the I/O buffer.
position_buffer = stream.tellg();

auto stream_view = detail::istreambuf(stream);

// ID
read_id(stream_view, options, id);

Expand Down
6 changes: 5 additions & 1 deletion include/seqan3/io/sequence_file/format_fastq.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ class format_fastq
id_type & id,
qual_type & qualities)
{
// Store current position in buffer
// Must happen before constructing the view.
// With libc++, tellg invalidates the I/O buffer.
position_buffer = stream.tellg();

auto stream_view = detail::istreambuf(stream);
auto stream_it = std::ranges::begin(stream_view);

Expand All @@ -117,7 +122,6 @@ class format_fastq
size_t sequence_size_after = 0;
if constexpr (!detail::decays_to_ignore_v<seq_type>)
sequence_size_before = size(sequence);
position_buffer = stream.tellg();

/* ID */
if (*stream_it != '@') // [[unlikely]]
Expand Down
17 changes: 10 additions & 7 deletions include/seqan3/io/sequence_file/format_genbank.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,14 @@ class format_genbank
id_type & id,
qual_type & SEQAN3_DOXYGEN_ONLY(qualities))
{
// Store current position in buffer
// Must happen before constructing the view.
// With libc++, tellg invalidates the I/O buffer.
position_buffer = stream.tellg();

auto stream_view = detail::istreambuf(stream);
auto stream_it = std::ranges::begin(stream_view);

// Store current position in buffer.
position_buffer = stream.tellg();

if (!(std::ranges::equal(stream_view | detail::take_until_or_throw(is_cntrl || is_blank),
std::string{"LOCUS"})))
throw parse_error{"An entry has to start with the code word LOCUS."};
Expand Down Expand Up @@ -162,8 +164,8 @@ class format_genbank
{
constexpr auto is_legal_alph = char_is_valid_for<seq_legal_alph_type>;
std::ranges::copy(
stream_view | std::views::filter(!(is_space || is_digit))
| detail::take_until_or_throw_and_consume(is_end) // consume "//"
stream_view | std::views::filter(!(is_space || is_digit)) // ignore whitespace and numbers
| detail::take_until_or_throw(is_end) // until //
| std::views::transform(
[is_legal_alph](char const c) // enforce legal alphabet
{
Expand All @@ -181,9 +183,10 @@ class format_genbank
}
else
{
detail::consume(stream_view | detail::take_until_or_throw_and_consume(is_end)); // consume until "//"
++stream_it; // consume "/n"
detail::consume(stream_view | detail::take_until_or_throw(is_end)); // consume until "//"
}

std::ranges::advance(stream_it, 3u, std::ranges::end(stream_view)); // Skip `//` and potentially '\n'
}

//!\copydoc sequence_file_output_format::write_sequence_record
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class fast_istreambuf_iterator
reference operator*() const
{
assert(stream_buf != nullptr);
assert(stream_buf->gptr() != stream_buf->egptr());
return *stream_buf->gptr();
}

Expand Down
4 changes: 2 additions & 2 deletions include/seqan3/search/configuration/parallel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace seqan3::search_cfg
*
* \include test/snippet/search/configuration_parallel.cpp
*/
using parallel =
seqan3::detail::parallel_mode<std::integral_constant<detail::search_config_id, detail::search_config_id::parallel>>;
using parallel = seqan3::detail::parallel_mode<
std::integral_constant<seqan3::detail::search_config_id, seqan3::detail::search_config_id::parallel>>;

} // namespace seqan3::search_cfg
31 changes: 14 additions & 17 deletions include/seqan3/search/detail/search_configurator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,23 +244,20 @@ algorithm_t search_configurator::configure_hit_strategy(configuration_t const &
auto cfg_without_hit = cfg.template remove<search_cfg::hit>();

// Apply the correct static configuration element.
return std::visit(multi_invocable{[&](search_cfg::hit_all_best)
{
return next_config_step(cfg_without_hit | search_cfg::hit_all_best{});
},
[&](search_cfg::hit_single_best)
{
return next_config_step(cfg_without_hit | search_cfg::hit_single_best{});
},
[&](search_cfg::hit_strata const & strata)
{
return next_config_step(cfg_without_hit | strata);
},
[&](auto)
{
return next_config_step(cfg_without_hit | search_cfg::hit_all{});
}},
hit_variant);
if (std::holds_alternative<search_cfg::hit_all_best>(hit_variant))
{
return next_config_step(cfg_without_hit | search_cfg::hit_all_best{});
}
else if (std::holds_alternative<search_cfg::hit_single_best>(hit_variant))
{
return next_config_step(cfg_without_hit | search_cfg::hit_single_best{});
}
else if (std::holds_alternative<search_cfg::hit_strata>(hit_variant))
{
return next_config_step(cfg_without_hit | std::get<search_cfg::hit_strata>(hit_variant));
}
else
return next_config_step(cfg_without_hit | search_cfg::hit_all{});
}
else // Already statically configured.
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,23 @@

using seqan3::detail::proxy_reference;

namespace std
template <typename T>
struct remove_reference
{
using type = std::remove_reference_t<T>;
};

template <typename T>
struct remove_reference<proxy_reference<T>>
{
using type = T;
};
} // namespace std

template <typename T>
using remove_reference_t = typename remove_reference<T>::type;

template <typename reference_t>
constexpr bool is_const_ref_v = std::is_const_v<std::remove_reference_t<reference_t>>;
constexpr bool is_const_ref_v = std::is_const_v<remove_reference_t<reference_t>>;

template <typename T>
using reference_test = ::testing::Test;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/alphabet/views/char_strictly_to_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@ TEST(view_char_strictly_to, exception)
std::string foo = "ACGPTA";

auto v = foo | seqan3::views::char_strictly_to<seqan3::dna5>;
EXPECT_THROW((std::ranges::equal(v, "ACGNTA"_dna5)), seqan3::invalid_char_assignment);
EXPECT_THROW(static_cast<void>(std::ranges::equal(v, "ACGNTA"_dna5)), seqan3::invalid_char_assignment);
}
2 changes: 1 addition & 1 deletion test/unit/alphabet/views/validate_char_for_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@ TEST(view_validate_char_for, exception)
std::string foo = "ACGPTA";

auto v = foo | seqan3::views::validate_char_for<seqan3::dna5>;
EXPECT_THROW((std::ranges::equal(v, "ACGNTA"sv)), seqan3::invalid_char_assignment);
EXPECT_THROW(static_cast<void>(std::ranges::equal(v, "ACGNTA"sv)), seqan3::invalid_char_assignment);
}
11 changes: 11 additions & 0 deletions test/unit/core/debug_stream_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,14 @@ TEST(debug_stream_test, byte)
o.flush();
EXPECT_EQ(o.str(), "40,244");
}

TEST(debug_stream_test, integers)
{
std::ostringstream o{};
seqan3::debug_stream_type my_stream{o};

my_stream << uint8_t{1} << ',' << uint16_t{2} << ',' << uint32_t{3} << ',' << uint64_t{4} << ',' << size_t{5} << ','
<< int8_t{6} << ',' << int16_t{7} << ',' << int32_t{8} << ',' << int64_t{9};
o.flush();
EXPECT_EQ(o.str(), "1,2,3,4,5,6,7,8,9");
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ DEFINITION Homo sapiens mRNA for prepro cortistatin like peptide, complete
ACCESSION ID3
ORIGIN
1 ACGTTTA
//
)"};
//)"};

std::string illegal_alphabet_character_input{
R"(LOCUS ID1
Expand Down
9 changes: 8 additions & 1 deletion test/unit/test/expect_same_type_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,19 @@ TEST(tuple, same_type_pass)

TEST(tuple, same_type_fail)
{
#ifdef _LIBCPP_VERSION
char const * error_message = "Expected equality of these values:\n"
" decltype(std::tuple{0, .0f, .0, 0u})\n"
" Which is: \"std::__1::tuple<int, float, double, unsigned int>\"\n"
" std::tuple<int, float, unsigned, double>\n"
" Which is: \"std::__1::tuple<int, float, unsigned int, double>\"";
#else
char const * error_message = "Expected equality of these values:\n"
" decltype(std::tuple{0, .0f, .0, 0u})\n"
" Which is: \"std::tuple<int, float, double, unsigned int>\"\n"
" std::tuple<int, float, unsigned, double>\n"
" Which is: \"std::tuple<int, float, unsigned int, double>\"";

#endif
auto && expect_result =
seqan3::test::expect_same_type{}("std::type_identity< decltype(std::tuple{0, .0f, .0, 0u})>{}",
"std::type_identity< std::tuple<int, float, unsigned, double>>{}",
Expand Down
21 changes: 21 additions & 0 deletions test/unit/test/sequence_generator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ TEST(random_sequence_generator, fixed_length)

seqan3::test::random_sequence_generator<seqan3::dna4_vector> random_sequence_generator{3};

#ifdef _LIBCPP_VERSION
EXPECT_EQ(random_sequence_generator(random_engine), "GTC"_dna4);
EXPECT_EQ(random_sequence_generator(random_engine), "GAG"_dna4);
#else
EXPECT_EQ(random_sequence_generator(random_engine), "TAG"_dna4);
EXPECT_EQ(random_sequence_generator(random_engine), "AGC"_dna4);
#endif
}

// generate (single) variable sized sequence, generates sequence with size ± size_variance.
Expand All @@ -35,9 +40,15 @@ TEST(random_sequence_generator, variable_length_and_different_random_engines)

seqan3::test::random_sequence_generator<seqan3::dna5_vector> random_sequence_generator{4, 2};

#ifdef _LIBCPP_VERSION
EXPECT_EQ(random_sequence_generator(random_engine1), "TCCGTT"_dna5);
EXPECT_EQ(random_sequence_generator(random_engine2), "CGTAAG"_dna5);
EXPECT_EQ(random_sequence_generator(random_engine3), "GA"_dna5);
#else
EXPECT_EQ(random_sequence_generator(random_engine1), "CCAN"_dna5);
EXPECT_EQ(random_sequence_generator(random_engine2), "NN"_dna5);
EXPECT_EQ(random_sequence_generator(random_engine3), "AG"_dna5);
#endif
}

// generate a collection of variable/fixed sized sequences
Expand All @@ -54,7 +65,11 @@ TEST(random_sequence_generator, sequence_collection)
return random_sequence_generator(random_engine);
});

#ifdef _LIBCPP_VERSION
std::vector<seqan3::dna5_vector> resulting_sequences = {"CTACN"_dna5, "AC"_dna5, "CTCGG"_dna5, "GGCANN"_dna5};
#else
std::vector<seqan3::dna5_vector> resulting_sequences = {"TA"_dna5, "GANG"_dna5, "TGNTCC"_dna5, "NNGC"_dna5};
#endif
EXPECT_EQ(sequences, resulting_sequences);
}

Expand All @@ -73,9 +88,15 @@ TEST(random_sequence_generator, sequence_pairs)
return {random_sequence_generator(random_engine), random_sequence_generator(random_engine)};
});

#ifdef _LIBCPP_VERSION
std::vector<std::tuple<seqan3::dna5_vector, seqan3::dna5_vector>> resulting_pairs{{"CTACN"_dna5, "AC"_dna5},
{"CTCGG"_dna5, "GGCANN"_dna5},
{"CACA"_dna5, "CNC"_dna5}};
#else
std::vector<std::tuple<seqan3::dna5_vector, seqan3::dna5_vector>> resulting_pairs{{"TA"_dna5, "GANG"_dna5},
{"TGNTCC"_dna5, "NNGC"_dna5},
{"GG"_dna5, "AA"_dna5}};
#endif

EXPECT_EQ(sequence_pairs, resulting_pairs);
}
4 changes: 4 additions & 0 deletions test/unit/utility/container/aligned_allocator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ TEST(aligned_allocator, in_list)

TEST(aligned_allocator, in_map)
{
#ifdef _LIBCPP_VERSION
GTEST_SKIP() << "std::map not aligned in libc++";
#else
constexpr size_t alignment = 16;
using key_type = char;
using value_type = int;
Expand All @@ -251,4 +254,5 @@ TEST(aligned_allocator, in_map)
EXPECT_EQ(memory_alignment(&*(++it), alignment), 0u);
EXPECT_EQ(memory_alignment(&*(++it), alignment), 0u);
EXPECT_EQ(++it, container.end());
#endif
}
4 changes: 4 additions & 0 deletions test/unit/utility/detail/type_name_as_string_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ class type_inspection : public ::testing::Test
"short*",
"double const* const",
"foo::bar<char> const &",
#ifdef _LIBCPP_VERSION
"foo::bar<foo::bar<char, double>>"};
#else
"foo::bar<foo::bar<char, double> >"};
#endif

public:
// Returns the name of the type according to the list of names defined above.
Expand Down

1 comment on commit fc8f4f7

@vercel
Copy link

@vercel vercel bot commented on fc8f4f7 Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

seqan3 – ./

seqan3-git-master-seqan.vercel.app
seqan3.vercel.app
seqan3-seqan.vercel.app

Please sign in to comment.