mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2025-02-21 20:59:46 +01:00
Porting rapidcheck to meson
This commit is contained in:
parent
be7219ad3d
commit
f5d6199f27
6816
include/doctest.h
Normal file
6816
include/doctest.h
Normal file
File diff suppressed because it is too large
Load Diff
39
meson.build
39
meson.build
@ -1,32 +1,40 @@
|
||||
project(
|
||||
'F.E.I.S.',
|
||||
'cpp',
|
||||
meson_version : '>=0.55.0',
|
||||
meson_version : '>=0.62.0',
|
||||
version : '1.1.0',
|
||||
default_options : ['cpp_std=c++20'],
|
||||
)
|
||||
|
||||
sources = []
|
||||
deps = []
|
||||
|
||||
sfml_system_dep = dependency('sfml-system', version : '>=2.5.1')
|
||||
deps += [sfml_system_dep]
|
||||
sfml_window_dep = dependency('sfml-window', version : '>=2.5.1')
|
||||
deps += [sfml_window_dep]
|
||||
sfml_graphics_dep = dependency('sfml-graphics', version : '>=2.5.1')
|
||||
deps += [sfml_graphics_dep]
|
||||
sfml_audio_dep = dependency('sfml-audio', version : '>=2.5.1')
|
||||
deps += [sfml_audio_dep]
|
||||
gl_dep = dependency('gl')
|
||||
deps += [gl_dep]
|
||||
openal_dep = dependency('openal')
|
||||
deps += [openal_dep]
|
||||
mpdecpp_dep = dependency('mpdec++', fallback: ['mpdecimal', 'mpdecpp_dep'])
|
||||
deps += [mpdecpp_dep]
|
||||
gmp_dep = dependency('gmp')
|
||||
deps += [gmp_dep]
|
||||
nowide_dep = dependency('nowide')
|
||||
deps += [nowide_dep]
|
||||
|
||||
# I chose to put the .cpp files of the libs I vendor directly in include/
|
||||
# I store the files in a (lib name -> files) dict so that tests can
|
||||
# select which libs they want to compile with
|
||||
include_sources = {}
|
||||
|
||||
subdir('include') # Defines `inc` and adds stuff in `include_sources`
|
||||
subdir('src') # Adds stuff in `sources`
|
||||
|
||||
deps = [
|
||||
dependency('sfml-system', version : '>=2.5.1'),
|
||||
dependency('sfml-window', version : '>=2.5.1'),
|
||||
dependency('sfml-graphics', version : '>=2.5.1'),
|
||||
dependency('sfml-audio', version : '>=2.5.1'),
|
||||
dependency('gl'),
|
||||
dependency('openal'),
|
||||
dependency('mpdec++', fallback: ['mpdecimal', 'mpdecpp_dep']),
|
||||
dependency('nowide'),
|
||||
dependency('gmp')
|
||||
]
|
||||
sources = []
|
||||
subdir('src') # Adds stuff in the `sources` list
|
||||
|
||||
subdir('tests')
|
||||
|
||||
@ -40,4 +48,3 @@ executable(
|
||||
dependencies: deps,
|
||||
include_directories: inc,
|
||||
)
|
||||
|
||||
|
@ -3,18 +3,19 @@
|
||||
#include <boost/multiprecision/gmp.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <json.hpp>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "special_numeric_types.hpp"
|
||||
|
||||
bool is_expressible_as_240th(const Fraction& beat) {
|
||||
return (240 * beat.get_num()) % beat.get_den() == 0;
|
||||
return (240 * beat.numerator()) % beat.denominator() == 0;
|
||||
};
|
||||
|
||||
nlohmann::ordered_json beat_to_best_form(const Fraction& beat) {
|
||||
if (is_expressible_as_240th(beat)) {
|
||||
return nlohmann::ordered_json(
|
||||
(240 * beat.get_num().get_ui()) / beat.get_den().get_ui()
|
||||
(240 * convert_to_u64(beat.numerator()) / convert_to_u64(beat.denominator())
|
||||
);
|
||||
} else {
|
||||
return beat_to_fraction_tuple(beat);
|
||||
@ -22,12 +23,12 @@ nlohmann::ordered_json beat_to_best_form(const Fraction& beat) {
|
||||
};
|
||||
|
||||
nlohmann::ordered_json beat_to_fraction_tuple(const Fraction& beat) {
|
||||
const auto integer_part = beat.get_num().get_ui() / beat.get_den().get_ui();
|
||||
const auto integral_part = static_cast<std::uint64_t>(beat);
|
||||
const auto remainder = beat % 1;
|
||||
return {
|
||||
integer_part,
|
||||
remainder.get_num().get_ui(),
|
||||
remainder.get_den().get_ui(),
|
||||
integral_part,
|
||||
convert_to_u64(remainder.numerator()),
|
||||
convert_to_u64(remainder.denominator()),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -86,11 +86,11 @@ namespace better {
|
||||
if (std::distance(begin, end) > 1) {
|
||||
std::stringstream ss;
|
||||
ss << "Attempted to create a Timing object with multiple ";
|
||||
ss << "BPMs defined at beat " << bpm_at_beat.get_beats().get_str();
|
||||
ss << "BPMs defined at beat " << bpm_at_beat.get_beats();
|
||||
ss << " :";
|
||||
std::for_each(begin, end, [&ss](auto b){
|
||||
ss << " (bpm: " << b.get_bpm() << ", beat: ";
|
||||
ss << b.get_beats().get_str() << "),";
|
||||
ss << b.get_beats() << "),";
|
||||
});
|
||||
throw std::invalid_argument(ss.str());
|
||||
}
|
||||
|
@ -30,4 +30,6 @@ sources += files(
|
||||
'toolbox.cpp',
|
||||
)
|
||||
|
||||
subdir('widgets')
|
||||
subdir('widgets')
|
||||
|
||||
subdir('tests')
|
@ -1,14 +1,85 @@
|
||||
#include "special_numeric_types.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
std::strong_ordering operator<=>(const Fraction& lhs, const Fraction& rhs) {
|
||||
const auto res = cmp(lhs, rhs);
|
||||
if (res > 0) {
|
||||
return std::strong_ordering::greater;
|
||||
} else if (res == 0) {
|
||||
return std::strong_ordering::equal;
|
||||
Fraction::Fraction(const Decimal& d) {
|
||||
const auto reduced = d.reduce();
|
||||
const mpq_class sign = (reduced.sign() > 0 ? 1 : -1);
|
||||
const mpq_class coefficient = reduced.coeff().u64();
|
||||
const auto exponent = reduced.exponent();
|
||||
const mpq_class power = fast_pow(mpq_class(10), std::abs(exponent));
|
||||
if (exponent >= 0) {
|
||||
value = sign * coefficient * power;
|
||||
} else {
|
||||
return std::strong_ordering::less;
|
||||
value = sign * coefficient / power;
|
||||
}
|
||||
}
|
||||
|
||||
Fraction::operator std::int64_t() const {
|
||||
const auto a = convert_to_i64(value.get_num());
|
||||
const auto b = convert_to_i64(value.get_den());
|
||||
return a / b;
|
||||
};
|
||||
|
||||
Fraction::operator std::uint64_t() const {
|
||||
const auto a = convert_to_u64(value.get_num());
|
||||
const auto b = convert_to_u64(value.get_den());
|
||||
return a / b;
|
||||
};
|
||||
|
||||
Fraction::operator double() const {
|
||||
return value.get_d();
|
||||
};
|
||||
|
||||
const mpz_class& Fraction::numerator() const {
|
||||
return value.get_num();
|
||||
}
|
||||
|
||||
const mpz_class& Fraction::denominator() const {
|
||||
return value.get_den();
|
||||
}
|
||||
|
||||
Fraction& Fraction::operator+=(const Fraction& rhs) {
|
||||
value += rhs.value;
|
||||
return *this;
|
||||
};
|
||||
|
||||
Fraction& Fraction::operator-=(const Fraction& rhs) {
|
||||
value -= rhs.value;
|
||||
return *this;
|
||||
};
|
||||
|
||||
Fraction& Fraction::operator*=(const Fraction& rhs) {
|
||||
value *= rhs.value;
|
||||
return *this;
|
||||
};
|
||||
|
||||
Fraction& Fraction::operator/=(const Fraction& rhs) {
|
||||
value /= rhs.value;
|
||||
return *this;
|
||||
};
|
||||
|
||||
bool Fraction::operator==(const Fraction& rhs) const {
|
||||
return value == rhs.value;
|
||||
};
|
||||
|
||||
Fraction operator+(Fraction lhs, const Fraction& rhs) {
|
||||
lhs+= rhs;
|
||||
return lhs;
|
||||
};
|
||||
|
||||
Fraction operator-(Fraction lhs, const Fraction& rhs) {
|
||||
lhs -= rhs;
|
||||
return lhs;
|
||||
};
|
||||
|
||||
Fraction operator*(Fraction lhs, const Fraction& rhs) {
|
||||
lhs *= rhs;
|
||||
return lhs;
|
||||
};
|
||||
|
||||
Fraction operator/(Fraction lhs, const Fraction& rhs) {
|
||||
lhs /= rhs;
|
||||
return lhs;
|
||||
};
|
||||
|
||||
// Thanks python !
|
||||
@ -16,13 +87,79 @@ std::strong_ordering operator<=>(const Fraction& lhs, const Fraction& rhs) {
|
||||
//
|
||||
// passing lhs by value helps optimize chained a+b+c, says cppreference
|
||||
Fraction operator%(Fraction lhs, const Fraction& rhs) {
|
||||
const auto da = lhs.get_den();
|
||||
const auto db = rhs.get_den();
|
||||
const auto na = lhs.get_num();
|
||||
const auto nb = rhs.get_num();
|
||||
const auto da = lhs.value.get_den();
|
||||
const auto db = rhs.value.get_den();
|
||||
const auto na = lhs.value.get_num();
|
||||
const auto nb = rhs.value.get_num();
|
||||
return Fraction{(na * db) % (nb * da), da * db};
|
||||
};
|
||||
|
||||
std::strong_ordering operator<=>(const Fraction& lhs, const Fraction& rhs) {
|
||||
auto res = cmp(lhs.value, rhs.value);
|
||||
if (res < 0) {
|
||||
return std::strong_ordering::less;
|
||||
} else if (res == 0) {
|
||||
return std::strong_ordering::equal;
|
||||
} else {
|
||||
return std::strong_ordering::greater;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Fraction& obj) {
|
||||
os << obj.value.get_str();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::int64_t convert_to_i64(const mpz_class& z) {
|
||||
if (z < mpz_int64_min or z > mpz_int64_max) {
|
||||
throw std::range_error(fmt::format(
|
||||
"number {} is too large to be represented by an std::int64_t",
|
||||
z.get_str()
|
||||
));
|
||||
}
|
||||
/* In absolute value, INT64_MIN is greater than INT64_MAX, so I can't take
|
||||
the absolute value of INT64_MIN and convert it to std::int64_t without
|
||||
triggering a signed overflow (which is UB ?).
|
||||
So I deal with it separately */
|
||||
if (z == mpz_int64_min) {
|
||||
return INT64_MIN;
|
||||
}
|
||||
const bool positive = z >= 0;
|
||||
const mpz_class abs = positive ? z : -z;
|
||||
/* We can only get unsigned longs from GMP (32 garanteed bits), so we have
|
||||
to split between low and high */
|
||||
const mpz_class low = abs & INT64_C(0x00000000ffffffff);
|
||||
const mpz_class high = abs >> 32;
|
||||
const auto low_ul = low.get_ui();
|
||||
const auto high_ul = high.get_ui();
|
||||
const auto low_i64 = static_cast<std::int64_t>(low_ul);
|
||||
const auto high_i64 = static_cast<std::int64_t>(high_ul);
|
||||
const auto abs_i64 = low_i64 + (high_i64 << 32);
|
||||
if (positive) {
|
||||
return abs_i64;
|
||||
} else {
|
||||
return -abs_i64;
|
||||
}
|
||||
}
|
||||
|
||||
std::uint64_t convert_to_u64(const mpz_class& z) {
|
||||
if (z < 0 or z > mpz_uint64_max) {
|
||||
throw std::range_error(fmt::format(
|
||||
"number {} is too large to be represented by an std::uint64_t",
|
||||
z.get_str()
|
||||
));
|
||||
}
|
||||
/* We can only get unsigned longs from GMP (32 garanteed bits), so we have
|
||||
to split between low and high */
|
||||
const mpz_class low = z & INT64_C(0x00000000ffffffff);
|
||||
const mpz_class high = z >> 32;
|
||||
const auto low_ul = low.get_ui();
|
||||
const auto high_ul = high.get_ui();
|
||||
const auto low_i64 = static_cast<std::uint64_t>(low_ul);
|
||||
const auto high_i64 = static_cast<std::uint64_t>(high_ul);
|
||||
return low_i64 + (high_i64 << 32);
|
||||
}
|
||||
|
||||
Fraction floor_fraction(const Fraction& f) {
|
||||
return f - (f % Fraction{1});
|
||||
};
|
||||
|
@ -1,16 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <type_traits>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <gmpxx.h>
|
||||
#include <libmpdec++/decimal.hh>
|
||||
|
||||
using Fraction = mpq_class;
|
||||
using Decimal = decimal::Decimal;
|
||||
|
||||
std::strong_ordering operator<=>(const Fraction& lhs, const Fraction& rhs);
|
||||
Fraction operator%(Fraction a, const Fraction& b);
|
||||
class Fraction {
|
||||
public:
|
||||
template<class ...Ts>
|
||||
Fraction(Ts&&... Args) requires (std::constructible_from<mpq_class, Ts...>) :
|
||||
value(std::forward<Ts>(Args)...)
|
||||
{
|
||||
value.canonicalize();
|
||||
};
|
||||
|
||||
explicit Fraction(const Decimal& d);
|
||||
explicit operator std::int64_t() const;
|
||||
explicit operator std::uint64_t() const;
|
||||
explicit operator double() const;
|
||||
|
||||
const mpz_class& numerator() const;
|
||||
const mpz_class& denominator() const;
|
||||
|
||||
Fraction& operator+=(const Fraction& rhs);
|
||||
Fraction& operator-=(const Fraction& rhs);
|
||||
Fraction& operator*=(const Fraction& rhs);
|
||||
Fraction& operator/=(const Fraction& rhs);
|
||||
bool operator==(const Fraction&) const;
|
||||
|
||||
friend Fraction operator+(Fraction a, const Fraction& b);
|
||||
friend Fraction operator-(Fraction a, const Fraction& b);
|
||||
friend Fraction operator*(Fraction a, const Fraction& b);
|
||||
friend Fraction operator/(Fraction a, const Fraction& b);
|
||||
friend Fraction operator%(Fraction a, const Fraction& b);
|
||||
friend std::strong_ordering operator<=>(const Fraction& lhs, const Fraction& rhs);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Fraction& obj);
|
||||
|
||||
private:
|
||||
mpq_class value;
|
||||
};
|
||||
|
||||
const auto mpz_uint64_max = mpz_class(fmt::format("{}", UINT64_MAX));
|
||||
const auto mpz_int64_min = mpz_class(fmt::format("{}", INT64_MIN));
|
||||
const auto mpz_int64_max = mpz_class(fmt::format("{}", INT64_MAX));
|
||||
|
||||
std::int64_t convert_to_i64(const mpz_class& z);
|
||||
std::uint64_t convert_to_u64(const mpz_class& z);
|
||||
|
||||
Fraction floor_fraction(const Fraction& f);
|
||||
Fraction round_fraction(const Fraction& f);
|
||||
Fraction convert_to_fraction(const Decimal& d);
|
||||
|
84
src/tests/doctest/fractions.cpp
Normal file
84
src/tests/doctest/fractions.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include <doctest.h>
|
||||
|
||||
#include "../../special_numeric_types.hpp"
|
||||
|
||||
TEST_CASE("Fractions") {
|
||||
SUBCASE("can be exactly constructed from") {
|
||||
SUBCASE("integers") {
|
||||
CHECK(Fraction{1} == Fraction{1,1});
|
||||
CHECK(Fraction{-2} == Fraction{-2,1});
|
||||
}
|
||||
SUBCASE("std::uint64_t") {
|
||||
CHECK(Fraction{UINT64_MAX, UINT64_C(1)} == Fraction{"18446744073709551615/1"});
|
||||
}
|
||||
SUBCASE("decimals") {
|
||||
CHECK(Fraction{Decimal{"0.0000000000000000001"}} == Fraction{"1/10000000000000000000"});
|
||||
CHECK(Fraction{Decimal{"12345.6789"}} == Fraction{123456789,10000});
|
||||
}
|
||||
}
|
||||
SUBCASE("can be cast to") {
|
||||
SUBCASE("std::int64_t, returing the integral part") {
|
||||
CHECK(static_cast<std::int64_t>(Fraction{1,2}) == INT64_C(0));
|
||||
CHECK(static_cast<std::int64_t>(Fraction{-5,2}) == INT64_C(-2));
|
||||
CHECK(static_cast<std::int64_t>(Fraction{"-9223372036854775808/1"}) == INT64_MIN);
|
||||
CHECK(static_cast<std::int64_t>(Fraction{"9223372036854775807/1"}) == INT64_MAX);
|
||||
CHECK(static_cast<std::int64_t>(Fraction{"-9000000000000000000/1"}) == INT64_C(-9000000000000000000));
|
||||
CHECK(static_cast<std::int64_t>(Fraction{"9000000000000000000/1"}) == INT64_C(9000000000000000000));
|
||||
}
|
||||
SUBCASE("std::uint64_t, returing the (positive) integral part") {
|
||||
CHECK(static_cast<std::uint64_t>(Fraction{1,2}) == UINT64_C(0));
|
||||
CHECK(static_cast<std::uint64_t>(Fraction{5,2}) == UINT64_C(2));
|
||||
CHECK(static_cast<std::uint64_t>(Fraction{"18446744073709551615/1"}) == UINT64_MAX);
|
||||
CHECK(static_cast<std::uint64_t>(Fraction{"12345678912345678912/1"}) == UINT64_C(12345678912345678912));
|
||||
}
|
||||
SUBCASE("doubles, returing the approximated value") {
|
||||
CHECK(static_cast<double>(Fraction{1,10}) == doctest::Approx(0.1));
|
||||
CHECK(static_cast<double>(Fraction{31,10}) == doctest::Approx(3.1));
|
||||
CHECK(static_cast<double>(Fraction{-1,10}) == doctest::Approx(-0.1));
|
||||
}
|
||||
}
|
||||
SUBCASE("are canonicalized upon creation") {
|
||||
CHECK(Fraction(0,4) == Fraction(0,1));
|
||||
CHECK(Fraction{2,4} == Fraction{1,2});
|
||||
CHECK(Fraction{1,-2} == Fraction{-1,2});
|
||||
}
|
||||
SUBCASE("are correctly compared") {
|
||||
CHECK(Fraction{1,2} > Fraction{1,3});
|
||||
CHECK(Fraction{-1,2} < Fraction{1,3});
|
||||
CHECK(Fraction{12,2} < Fraction{28, 4});
|
||||
}
|
||||
SUBCASE("are not turned into another type after binary operands") {
|
||||
CHECK(std::is_same_v<decltype(Fraction{1,2} + Fraction{1,3}), Fraction>);
|
||||
CHECK(std::is_same_v<decltype(Fraction{1,2} - Fraction{1,3}), Fraction>);
|
||||
CHECK(std::is_same_v<decltype(Fraction{1,2} * Fraction{1,3}), Fraction>);
|
||||
CHECK(std::is_same_v<decltype(Fraction{1,2} / Fraction{1,3}), Fraction>);
|
||||
CHECK(std::is_same_v<decltype(Fraction{1,2} % Fraction{1,3}), Fraction>);
|
||||
}
|
||||
SUBCASE("add correctly") {
|
||||
CHECK(Fraction{1,2} + Fraction{1,3} == Fraction{5,6});
|
||||
CHECK(Fraction{-1,2} + Fraction{1,2} == Fraction{0,1});
|
||||
}
|
||||
SUBCASE("subtract correctly") {
|
||||
CHECK(Fraction{1,2} - Fraction{1,3} == Fraction{1,6});
|
||||
CHECK(Fraction{-1,2} - Fraction{1,2} == Fraction{-1,1});
|
||||
}
|
||||
SUBCASE("multiply correctly") {
|
||||
CHECK(Fraction{1,2} * Fraction{1,7} == Fraction{1,14});
|
||||
CHECK(Fraction{-1,2} * Fraction{1,2} == Fraction{-1,4});
|
||||
}
|
||||
SUBCASE("divide correctly") {
|
||||
CHECK(Fraction{1,2} / Fraction{1,7} == Fraction{7,2});
|
||||
CHECK(Fraction{-1,2} / Fraction{1,2} == Fraction{-1,1});
|
||||
}
|
||||
SUBCASE("support binary operand with") {
|
||||
SUBCASE("integer literals") {
|
||||
CHECK(Fraction{1,2} + 1 == Fraction{3,2});
|
||||
CHECK(Fraction{1,3} - 1 == Fraction{-2,3});
|
||||
CHECK(Fraction{1,4} * 2 == Fraction{1,2});
|
||||
CHECK(Fraction{1,5} / 2 == Fraction{1,10});
|
||||
}
|
||||
SUBCASE("floating point literals") {
|
||||
CHECK(Fraction{1,2} + 1.0 == Fraction{3,2});
|
||||
}
|
||||
}
|
||||
}
|
2
src/tests/doctest/main.cpp
Normal file
2
src/tests/doctest/main.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include <doctest.h>
|
19
src/tests/doctest/meson.build
Normal file
19
src/tests/doctest/meson.build
Normal file
@ -0,0 +1,19 @@
|
||||
doctest_tests = executable(
|
||||
'doctest_tests',
|
||||
'main.cpp',
|
||||
'fractions.cpp',
|
||||
'../../special_numeric_types.cpp',
|
||||
include_sources['fmt'],
|
||||
dependencies: [
|
||||
gmp_dep,
|
||||
mpdecpp_dep,
|
||||
],
|
||||
include_directories: inc,
|
||||
)
|
||||
|
||||
test(
|
||||
'doctest',
|
||||
doctest_tests,
|
||||
args: ['--force-colors=true'],
|
||||
verbose: true,
|
||||
)
|
2
src/tests/meson.build
Normal file
2
src/tests/meson.build
Normal file
@ -0,0 +1,2 @@
|
||||
subdir('doctest')
|
||||
subdir('rapidcheck')
|
19
src/tests/rapidcheck/meson.build
Normal file
19
src/tests/rapidcheck/meson.build
Normal file
@ -0,0 +1,19 @@
|
||||
rapidcheck_tests = executable(
|
||||
'rapidcheck_tests',
|
||||
'rapidcheck_main.cpp',
|
||||
'test_fractions.cpp',
|
||||
'../../special_numeric_types.cpp',
|
||||
include_sources['fmt'],
|
||||
dependencies: [
|
||||
gmp_dep,
|
||||
mpdecpp_dep,
|
||||
dependency('rapidcheck')
|
||||
],
|
||||
include_directories: inc,
|
||||
)
|
||||
|
||||
test(
|
||||
'rapidcheck',
|
||||
rapidcheck_tests,
|
||||
verbose: true,
|
||||
)
|
6
src/tests/rapidcheck/rapidcheck_main.cpp
Normal file
6
src/tests/rapidcheck/rapidcheck_main.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <rapidcheck.h>
|
||||
|
||||
int main() {
|
||||
|
||||
return 0;
|
||||
}
|
7
subprojects/rapidcheck.wrap
Normal file
7
subprojects/rapidcheck.wrap
Normal file
@ -0,0 +1,7 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/emil-e/rapidcheck
|
||||
# closest commit to v11.1.4 on the standalone branch
|
||||
revision = head
|
||||
# Overlays subproject/packagefiles/nowide over the fresh git
|
||||
# clone of nowide
|
||||
patch_directory = rapidcheck
|
Loading…
x
Reference in New Issue
Block a user