From 5dc1e75f84b92e2e209a25d91e0b891f9ae7fda2 Mon Sep 17 00:00:00 2001 From: quasar Date: Thu, 12 Nov 2026 18:26:58 +0000 Subject: [PATCH 1/2] Refactor tests to the CTest framework (issue 38) - main test executable: every test is now implemented in its own function (test_noise2, test_noise3, test_noise4); main() only selects and runs the tests (all of them or one by name). - Use the CTest framework: enable_testing() + add_test() per test, replacing the custom deployTest/test targets of the QuasarApp CMake module (the 'test' build target now invokes ctest). - The tests also range-check all 2D/3D/4D lattice orientation variants. - Update CI: the test target runs ctest, so the CQtDeployer deploy step is no longer needed. - Update the README tests section accordingly. --- .github/workflows/ci.yml | 27 ++- CMakeLists.txt | 6 +- README.md | 27 ++- tests/CMakeLists.txt | 16 +- tests/test_OpenSimplex2F.c | 359 +++++++++++++++++++++++++++++-------- 5 files changed, 341 insertions(+), 94 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12f2b08..e4b542c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,10 @@ name: Build and Test -# Builds the OpenSimplex2 CMake project and runs its internal `test` target. -# The `test` target (created by the QuasarApp CMake module, initTests/addTests) -# first deploys the test executable with `cqtdeployer` (deployTest* target) and -# then executes the generated runner, so cqtdeployer must be installed on PATH -# before the test step (see the CQtDeployer install action below). +# Builds the OpenSimplex2 CMake project and runs its tests via CTest. +# `enable_testing()` creates the `test` build target which executes all +# tests registered with add_test() in tests/CMakeLists.txt (see +# "Testing With CMake and CTest", CMake documentation). on: pull_request: types: [opened, synchronize, reopened] @@ -27,9 +26,8 @@ jobs: build_type: [Release] steps: - # The project is a plain C application (no Qt). On Windows the test source - # uses __attribute__((unused)) (GCC-only, MSVC cannot build it), so a MinGW - # toolchain is required: the aqt MinGW (tools_mingw1310) provides the gcc + # The project is a plain C application (no Qt). On Windows a MinGW + # toolchain is used: the aqt MinGW (tools_mingw1310) provides the gcc # compiler and qmake. - name: Install Qt (Windows) uses: jurplel/install-qt-action@v4.3.1 @@ -62,14 +60,8 @@ jobs: with: key: ${{ matrix.os }}-${{ matrix.build_type }} - # The `test` target deploys the test binary with cqtdeployer, so install it. - # No version pin: the install action downloads the latest stable - # CQtDeployer release by default (latest: true). - - name: Install CQtDeployer - uses: QuasarApp/cqtdeployer-install-action@v1.1.0 - - # The test executable links against libpng (find_package(PNG REQUIRED)) and writes - # test2d/3d/4d.png at runtime. + # The test executable links against libpng (find_package(PNG REQUIRED)) and + # writes test2d/3d/4d.png at runtime. - name: Install libpng (Linux) if: runner.os == 'Linux' run: | @@ -122,6 +114,7 @@ jobs: - name: ccache statistics run: ccache -s - # Runs the internal CMake `test` target (deploys + executes the test binary). + # Runs the `test` build target: it invokes CTest, which executes every + # test registered in tests/CMakeLists.txt (test_noise2/3/4). - name: Run Tests run: cmake --build ${{ github.workspace }}/build --target test diff --git a/CMakeLists.txt b/CMakeLists.txt index d42ad59..92a6896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,9 +33,11 @@ target_link_libraries(${CURRENT_PROJECT} INTERFACE ${CURRENT_PROJECT}C) option(OPENSIMPLEX2_TESTS "This option disables or enables tests of the ${PROJECT_NAME} project" ON) -initAll() - if (OPENSIMPLEX2_TESTS) + # CTest framework (see "Testing With CMake and CTest" chapter of the + # CMake documentation): enable_testing() creates the `test` build target + # that runs all tests registered in the tests/ subdirectory with ctest. + enable_testing() add_subdirectory(tests) else() message("The ${PROJECT_NAME} tests is disabled.") diff --git a/README.md b/README.md index b7df6cd..8391d25 100644 --- a/README.md +++ b/README.md @@ -133,10 +133,15 @@ The Makefile also builds the `test_OpenSimplex2F` binary (test source in ### Tests +The tests use the [CTest](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Testing%20With%20CMake%20and%20CTest.html) +framework. The main test executable (`OpenSimplex2tests`, built from +`tests/test_OpenSimplex2F.c`) implements every test in its own function +(`test_noise2`, `test_noise3`, `test_noise4`); each of them is registered +as a separate CTest test (see `tests/CMakeLists.txt`). + To build the tests, keep the `OPENSIMPLEX2_TESTS` option enabled (default -`ON`) and run the `test` target — it builds the `OpenSimplex2tests` -executable from the `tests/` subdirectory and runs it (the targets are -registered with the `addTests()` function of the QuasarApp CMake module): +`ON`) and run the `test` target — it invokes CTest and executes all +registered tests: ``` cmake -B build @@ -144,6 +149,22 @@ cmake --build build cmake --build build --target test ``` +Individual tests can be run separately with CTest: + +``` +ctest --test-dir build -R test_noise3 +``` + +or by passing the test name to the executable: + +``` +build/tests/OpenSimplex2tests test_noise3 +``` + +The tests write 2D/3D/4D noise images (requires libpng) into the test +directory of the build tree and check that all noise values stay within +the expected `[-1, 1]` range. + ## License This project is provided under the license defined in the diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 46f59b5..b3404a7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,5 +19,17 @@ target_include_directories(${CURRENT_PROJECT} PRIVATE "${CMAKE_CURRENT_SOURCE_DI target_compile_options(${CURRENT_PROJECT} PRIVATE -Wall -Wextra --pedantic) target_link_libraries(${CURRENT_PROJECT} PRIVATE OpenSimplex2Interface m PNG::PNG) -initTests() -addTests(${PROJECT_NAME} ${CURRENT_PROJECT}) +# CTest framework: every test function of the main test executable +# (test_noise2, test_noise3, test_noise4) is registered as a separate +# CTest test, so each of them can be run individually, e.g.: +# ctest -R test_noise2 +# or all together (the `test` build target / `ctest` from the build dir). +# The generated PNG images are written to the build directory, not to the +# source tree. +set(TEST_NAMES test_noise2 test_noise3 test_noise4) + +foreach(test_name IN LISTS TEST_NAMES) + add_test(NAME ${test_name} + COMMAND ${CURRENT_PROJECT} ${test_name} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +endforeach() diff --git a/tests/test_OpenSimplex2F.c b/tests/test_OpenSimplex2F.c index 5c5fd84..21847f2 100644 --- a/tests/test_OpenSimplex2F.c +++ b/tests/test_OpenSimplex2F.c @@ -2,6 +2,20 @@ * Copyright (C) 2026 QuasarApp Group DOO * Licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0), * see the accompanying LICENSE file. + * + * Main test executable of the OpenSimplex2 project. + * + * Every test is implemented in its own function: + * - test_noise2() 2D noise: OpenSimplex2F_noise2, noise2_XBeforeY + * - test_noise3() 3D noise: noise3_Classic, noise3_XYBeforeZ, noise3_XZBeforeY + * - test_noise4() 4D noise: noise4_Classic (3-octave blend), + * noise4_XYBeforeZW, noise4_XZBeforeYW, + * noise4_XYZBeforeW + * + * main() only selects and runs the tests: with no argument it runs all of + * them, with one argument it runs the test with that name only. The tests + * are registered in the CTest framework (see tests/CMakeLists.txt), so each + * of them can also be run separately, e.g.: ctest -R test_noise2 */ #include @@ -20,6 +34,21 @@ #define HEIGHT 512 #define FEATURE_SIZE 24 +/* All OpenSimplex2F variants are defined to return values in [-1, 1]. + * The 3-octave blend of the 4D image is a convex combination of the same + * functions, so it stays in the same range. A small tolerance covers + * floating point rounding. */ +#define NOISE_LIMIT 1.0 +#define NOISE_EPSILON 1e-6 + +/* Seed shared by every test, keeps the results reproducible. */ +#define TEST_SEED 77374 + +/* z/w offsets used when range-checking the 3D/4D variants off the image + * plane, so the extra dimensions are actually exercised. */ +#define Z_OFFSET 0.37 +#define W_OFFSET 0.71 + static int write_png_image(const char *filename, unsigned char *pixels, int w, int h, int has_alpha) { png_structp png_ptr; @@ -103,28 +132,26 @@ static void stats_add(struct noise_stats *s, double value) s->sum += value; } -/* All OpenSimplex2F variants are defined to return values in [-1, 1]. - * The 3-octave blend of the 2D image is a convex combination of the same - * functions, so it stays in the same range. A small tolerance covers - * floating point rounding. */ -#define NOISE_LIMIT 1.0 -#define NOISE_EPSILON 1e-6 +static int stats_in_range(const struct noise_stats *s) +{ + return (s->min >= -NOISE_LIMIT - NOISE_EPSILON) && + (s->max <= NOISE_LIMIT + NOISE_EPSILON); +} -static int report_test(int index, int total, const char *name, const char *png, +static int report_test(const char *name, const char *png, int write_rc, const struct noise_stats *s) { struct stat file; long long size = 0; double mean = s->sum / (double) (WIDTH * HEIGHT); - int in_range = (s->min >= -NOISE_LIMIT - NOISE_EPSILON) && - (s->max <= NOISE_LIMIT + NOISE_EPSILON); + int in_range = stats_in_range(s); int wrote = (write_rc == 0) && (stat(png, &file) == 0); int ok = in_range && wrote; if (wrote) size = (long long) file.st_size; - printf(" [%d/%d] %-32s min=% .6f max=% .6f mean=% .6f -> %s (%lld bytes) ... %s\n", - index, total, name, s->min, s->max, mean, png, size, + printf(" %-40s min=% .6f max=% .6f mean=% .6f -> %s (%lld bytes) ... %s\n", + name, s->min, s->max, mean, png, size, ok ? "PASS" : "FAIL"); if (!in_range) printf(" noise value outside the expected range [-1, 1]\n"); @@ -135,80 +162,272 @@ static int report_test(int index, int total, const char *name, const char *png, return ok; } -int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) +/* Range-check one 2D noise variant over a half-resolution grid. + * Returns 1 on pass, 0 on fail. */ +static int check_noise2_variant(struct OpenSimplex2F_context *ctx, const char *name, + double (*f)(struct OpenSimplex2F_context *, double, double)) { - int x, y; - double value; - double v0, v1, v2; /* values from different octaves. */ - uint32_t rgb; - int passed = 0; - /* Static storage: 3 x 1MB arrays would not fit the default Windows + struct noise_stats s; + int x, y, ok; + + stats_init(&s); + for (y = 0; y < HEIGHT; y += 2) + for (x = 0; x < WIDTH; x += 2) + stats_add(&s, f(ctx, (double) x / FEATURE_SIZE, (double) y / FEATURE_SIZE)); + ok = stats_in_range(&s); + printf(" %-40s min=% .6f max=% .6f ... %s\n", + name, s.min, s.max, ok ? "PASS" : "FAIL"); + if (!ok) + printf(" noise value outside the expected range [-1, 1]\n"); + return ok; +} + +/* Range-check one 3D noise variant over a half-resolution grid at + * z = Z_OFFSET. Returns 1 on pass, 0 on fail. */ +static int check_noise3_variant(struct OpenSimplex2F_context *ctx, const char *name, + double (*f)(struct OpenSimplex2F_context *, double, double, double)) +{ + struct noise_stats s; + int x, y, ok; + + stats_init(&s); + for (y = 0; y < HEIGHT; y += 2) + for (x = 0; x < WIDTH; x += 2) + stats_add(&s, f(ctx, (double) x / FEATURE_SIZE, + (double) y / FEATURE_SIZE, Z_OFFSET)); + ok = stats_in_range(&s); + printf(" %-40s min=% .6f max=% .6f ... %s\n", + name, s.min, s.max, ok ? "PASS" : "FAIL"); + if (!ok) + printf(" noise value outside the expected range [-1, 1]\n"); + return ok; +} + +/* Range-check one 4D noise variant over a half-resolution grid at + * z = Z_OFFSET, w = W_OFFSET. Returns 1 on pass, 0 on fail. */ +static int check_noise4_variant(struct OpenSimplex2F_context *ctx, const char *name, + double (*f)(struct OpenSimplex2F_context *, double, double, double, double)) +{ + struct noise_stats s; + int x, y, ok; + + stats_init(&s); + for (y = 0; y < HEIGHT; y += 2) + for (x = 0; x < WIDTH; x += 2) + stats_add(&s, f(ctx, (double) x / FEATURE_SIZE, + (double) y / FEATURE_SIZE, Z_OFFSET, W_OFFSET)); + ok = stats_in_range(&s); + printf(" %-40s min=% .6f max=% .6f ... %s\n", + name, s.min, s.max, ok ? "PASS" : "FAIL"); + if (!ok) + printf(" noise value outside the expected range [-1, 1]\n"); + return ok; +} + +/* --------------------------------------------------------------------------- + * Test functions. Each one is a separate test case of the main test + * executable and is registered as its own CTest test. Every function + * creates its own noise context, renders/checks the requested noise + * functions and returns 0 on success, 1 on failure. + * ------------------------------------------------------------------------- */ + +/* 2D test: renders test2d.png from OpenSimplex2F_noise2 and range-checks + * the alternative 2D orientation. */ +static int test_noise2(void) +{ + /* Static storage: a 1MB array would not fit the default Windows * thread stack (1MB) and crash with STATUS_STACK_BUFFER_OVERRUN - * (0xC000013D); Linux survives them only because its default stack + * (0xC000013D); Linux survives it only because its default stack * is 8MB. */ - static uint32_t image2d[HEIGHT][WIDTH]; - static uint32_t image3d[HEIGHT][WIDTH]; - static uint32_t image4d[HEIGHT][WIDTH]; - struct OpenSimplex2F_context *ctx; - struct noise_stats st2d, st3d, st4d; -#if defined(SINGLE_OCTAVE) - static const char *name2d = "open_simplex_noise4 (1 octave)"; -#else - static const char *name2d = "open_simplex_noise4 (3 octaves)"; -#endif - - stats_init(&st2d); - stats_init(&st3d); - stats_init(&st4d); + static uint32_t image[HEIGHT][WIDTH]; + struct OpenSimplex2F_context *ctx = NULL; + struct noise_stats s; + uint32_t rgb; + int x, y, ok = 1; - printf("OpenSimplex2F tests (seed 77374, image %dx%d)\n", WIDTH, HEIGHT); - OpenSimplex2F(77374, &ctx); + if (OpenSimplex2F(TEST_SEED, &ctx) != 0) { + printf(" OpenSimplex2F() failed\n"); + return 1; + } + stats_init(&s); for (y = 0; y < HEIGHT; y++) { for (x = 0; x < WIDTH; x++) { -#if defined(SINGLE_OCTAVE) - value = open_simplex_noise4(ctx, (double) x / FEATURE_SIZE, (double) y / FEATURE_SIZE, 0.0, 0.0); -#else - /* Use three octaves: frequency N, N/2 and N/4 with relative amplitudes 4:2:1. */ - v0 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 4, - (double) y / FEATURE_SIZE / 4, 0.0, 0.0); - v1 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 2, - (double) y / FEATURE_SIZE / 2, 0.0, 0.0); - v2 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 1, - (double) y / FEATURE_SIZE / 1, 0.0, 0.0); - value = v0 * 4 / 7.0 + v1 * 2 / 7.0 + v2 * 1 / 7.0; -#endif - stats_add(&st2d, value); + double value = OpenSimplex2F_noise2(ctx, (double) x / FEATURE_SIZE, (double) y / FEATURE_SIZE); + stats_add(&s, value); rgb = 0x010101 * (uint32_t) ((value + 1) * 127.5); - image2d[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); + image[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); + } + } + + if (!report_test("OpenSimplex2F_noise2", "test2d.png", + write_png_image("test2d.png", (unsigned char *) image, WIDTH, HEIGHT, 1), + &s)) + ok = 0; + if (!check_noise2_variant(ctx, "OpenSimplex2F_noise2_XBeforeY", OpenSimplex2F_noise2_XBeforeY)) + ok = 0; + + OpenSimplex2F_free(ctx); + return ok ? 0 : 1; +} - value = OpenSimplex2F_noise2(ctx, (double) x / FEATURE_SIZE, (double) y / FEATURE_SIZE); - stats_add(&st3d, value); +/* 3D test: renders test3d.png from OpenSimplex2F_noise3_Classic and + * range-checks the alternative 3D orientations. */ +static int test_noise3(void) +{ + static uint32_t image[HEIGHT][WIDTH]; + struct OpenSimplex2F_context *ctx = NULL; + struct noise_stats s; + uint32_t rgb; + int x, y, ok = 1; + + if (OpenSimplex2F(TEST_SEED, &ctx) != 0) { + printf(" OpenSimplex2F() failed\n"); + return 1; + } + + stats_init(&s); + for (y = 0; y < HEIGHT; y++) { + for (x = 0; x < WIDTH; x++) { + double value = OpenSimplex2F_noise3_Classic(ctx, (double) x / FEATURE_SIZE, + (double) y / FEATURE_SIZE, 0.0); + stats_add(&s, value); rgb = 0x010101 * (uint32_t) ((value + 1) * 127.5); - image3d[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); + image[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); + } + } + + if (!report_test("OpenSimplex2F_noise3_Classic", "test3d.png", + write_png_image("test3d.png", (unsigned char *) image, WIDTH, HEIGHT, 1), + &s)) + ok = 0; + if (!check_noise3_variant(ctx, "OpenSimplex2F_noise3_XYBeforeZ", OpenSimplex2F_noise3_XYBeforeZ)) + ok = 0; + if (!check_noise3_variant(ctx, "OpenSimplex2F_noise3_XZBeforeY", OpenSimplex2F_noise3_XZBeforeY)) + ok = 0; + + OpenSimplex2F_free(ctx); + return ok ? 0 : 1; +} - value = OpenSimplex2F_noise3_Classic(ctx, (double) x / FEATURE_SIZE, (double) y / FEATURE_SIZE, 0.0); - stats_add(&st4d, value); +/* 4D test: renders test4d.png from a 3-octave blend of + * OpenSimplex2F_noise4_Classic and range-checks the alternative + * 4D orientations. */ +static int test_noise4(void) +{ + static uint32_t image[HEIGHT][WIDTH]; + struct OpenSimplex2F_context *ctx = NULL; + struct noise_stats s; + uint32_t rgb; + int x, y, ok = 1; + + if (OpenSimplex2F(TEST_SEED, &ctx) != 0) { + printf(" OpenSimplex2F() failed\n"); + return 1; + } + + stats_init(&s); + for (y = 0; y < HEIGHT; y++) { + for (x = 0; x < WIDTH; x++) { + /* Use three octaves: frequency N, N/2 and N/4 with relative amplitudes 4:2:1. */ + double v0 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 4, + (double) y / FEATURE_SIZE / 4, 0.0, 0.0); + double v1 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 2, + (double) y / FEATURE_SIZE / 2, 0.0, 0.0); + double v2 = OpenSimplex2F_noise4_Classic(ctx, (double) x / FEATURE_SIZE / 1, + (double) y / FEATURE_SIZE / 1, 0.0, 0.0); + double value = v0 * 4 / 7.0 + v1 * 2 / 7.0 + v2 * 1 / 7.0; + + stats_add(&s, value); rgb = 0x010101 * (uint32_t) ((value + 1) * 127.5); - image4d[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); + image[y][x] = ((uint32_t) 0x0ff << 24) | (rgb); } } - if (report_test(1, 3, name2d, "test2d.png", - write_png_image("test2d.png", (unsigned char *) image2d, WIDTH, HEIGHT, 1), - &st2d)) - passed++; - if (report_test(2, 3, "OpenSimplex2F_noise2", "test3d.png", - write_png_image("test3d.png", (unsigned char *) image3d, WIDTH, HEIGHT, 1), - &st3d)) - passed++; - if (report_test(3, 3, "OpenSimplex2F_noise3_Classic", "test4d.png", - write_png_image("test4d.png", (unsigned char *) image4d, WIDTH, HEIGHT, 1), - &st4d)) - passed++; + + if (!report_test("OpenSimplex2F_noise4 (3 octaves)", "test4d.png", + write_png_image("test4d.png", (unsigned char *) image, WIDTH, HEIGHT, 1), + &s)) + ok = 0; + if (!check_noise4_variant(ctx, "OpenSimplex2F_noise4_XYBeforeZW", OpenSimplex2F_noise4_XYBeforeZW)) + ok = 0; + if (!check_noise4_variant(ctx, "OpenSimplex2F_noise4_XZBeforeYW", OpenSimplex2F_noise4_XZBeforeYW)) + ok = 0; + if (!check_noise4_variant(ctx, "OpenSimplex2F_noise4_XYZBeforeW", OpenSimplex2F_noise4_XYZBeforeW)) + ok = 0; + OpenSimplex2F_free(ctx); - OpenSimplex2F_shutdown(); - printf("Result: %d/3 tests passed\n", passed); - return (passed == 3) ? 0 : 1; + return ok ? 0 : 1; } +/* --------------------------------------------------------------------------- + * Test registry and the main test executable entry point. + * ------------------------------------------------------------------------- */ + +struct test_case { + const char *name; + int (*run)(void); +}; + +static const struct test_case all_tests[] = { + { "test_noise2", test_noise2 }, + { "test_noise3", test_noise3 }, + { "test_noise4", test_noise4 }, +}; + +#define TEST_COUNT (sizeof(all_tests) / sizeof(all_tests[0])) + +static void print_usage(const char *prog) +{ + size_t i; + printf("usage: %s [test-name]\n", prog); + printf("available tests:\n"); + for (i = 0; i < TEST_COUNT; i++) + printf(" %s\n", all_tests[i].name); +} + +int main(int argc, char *argv[]) +{ + size_t i; + int selected = -1; + int ran = 0, failed = 0; + + if (argc > 2) { + print_usage(argv[0]); + return 2; + } + + if (argc == 2) { + for (i = 0; i < TEST_COUNT; i++) { + if (strcmp(argv[1], all_tests[i].name) == 0) { + selected = (int) i; + break; + } + } + if (selected < 0) { + printf("unknown test: %s\n", argv[1]); + print_usage(argv[0]); + return 2; + } + } + + printf("OpenSimplex2F tests (seed %d, image %dx%d)\n", TEST_SEED, WIDTH, HEIGHT); + + if (selected >= 0) { + printf("== %s ==\n", all_tests[selected].name); + if (all_tests[selected].run() != 0) + failed++; + ran = 1; + } else { + for (i = 0; i < TEST_COUNT; i++) { + printf("== %s ==\n", all_tests[i].name); + if (all_tests[i].run() != 0) + failed++; + ran++; + } + } + + OpenSimplex2F_shutdown(); + printf("Result: %d/%d tests passed\n", ran - failed, ran); + return failed ? 1 : 0; +} From 18ecb679d32148b5c73147bc478ad811adc26146 Mon Sep 17 00:00:00 2001 From: quasar Date: Thu, 12 Nov 2026 19:41:10 +0000 Subject: [PATCH 2/2] Remove the aqt Qt installation from the CI workflows (issue 38) --- .github/workflows/ci.yml | 46 ++++++---------- .github/workflows/cross-platform-compare.yml | 56 ++++++-------------- 2 files changed, 30 insertions(+), 72 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4b542c..d589dd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,29 +26,11 @@ jobs: build_type: [Release] steps: - # The project is a plain C application (no Qt). On Windows a MinGW - # toolchain is used: the aqt MinGW (tools_mingw1310) provides the gcc - # compiler and qmake. - - name: Install Qt (Windows) - uses: jurplel/install-qt-action@v4.3.1 - if: runner.os == 'Windows' - with: - version: '6.10.3' # aqt has bug with latest qt versions in windows - target: 'desktop' - arch: 'win64_mingw' - cache: true - tools: 'tools_mingw1310' - aqtversion: ==3.3.* - - - name: Install Qt (Linux) - uses: jurplel/install-qt-action@v4.3.1 - if: runner.os == 'Linux' - with: - version: '6.12.0' - target: 'desktop' - arch: 'linux_gcc_64' - cache: true - aqtversion: ==3.3.* + # The project is a plain C application (no Qt), so no Qt installation + # is required: the CMake project (submodule/CMake/QuasarApp.cmake) only + # looks qmake up at configure time and continues if it is not found. + # Linux uses the pre-installed gcc, Windows the MinGW gcc installed + # from MSYS2 below. - name: Checkout uses: actions/checkout@v4 @@ -68,19 +50,22 @@ jobs: sudo apt-get update sudo apt-get install -y libpng-dev - # The aqt MinGW does not ship libpng, so install the MinGW libpng from MSYS2 and - # point CMake at it (see the Windows configure step). - - name: Install libpng (Windows) + # The MinGW gcc compiler (mingw-w64-x86_64-gcc) and the MinGW libpng + # are installed from MSYS2 and CMake is pointed at the msys2 mingw64 + # root (see the Windows configure step). + - name: Install MinGW gcc and libpng (Windows) id: msys2 if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 with: msystem: MINGW64 - install: mingw-w64-x86_64-libpng + install: mingw-w64-x86_64-gcc mingw-w64-x86_64-libpng + suppress-deprecation-warnings: msystem-mingw64 - # setup-msys2 only adds the MSYS2 root to the Windows PATH, so the test - # executable would not find libpng16-16.dll (and libz-1.dll) at runtime and - # fails with 0xc0000135 (STATUS_DLL_NOT_FOUND). Add the mingw64 bin + # setup-msys2 only adds the MSYS2 root to the Windows PATH, so the gcc + # compiler (the configure step) and the test executable (libpng16-16.dll + # and libz-1.dll at runtime) would not be found and the tests would + # fail with 0xc0000135 (STATUS_DLL_NOT_FOUND). Add the mingw64 bin # directory to the PATH for the build/test steps. - name: Add MSYS2 mingw64 bin to PATH (Windows) if: runner.os == 'Windows' @@ -105,7 +90,6 @@ jobs: -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_C_COMPILER_LAUNCHER=ccache - -DCMAKE_PREFIX_PATH=${{ env.QT_ROOT_DIR }} -S ${{ github.workspace }} - name: Build diff --git a/.github/workflows/cross-platform-compare.yml b/.github/workflows/cross-platform-compare.yml index c4dc090..9fb4625 100644 --- a/.github/workflows/cross-platform-compare.yml +++ b/.github/workflows/cross-platform-compare.yml @@ -40,39 +40,11 @@ jobs: platform: macos steps: - # The project is plain C (no Qt code), but the CMake project - # (submodule/CMake/QuasarApp.cmake) looks for qmake at configure time, - # so Qt must be installed on every platform (same setup as ci.yml). - - name: Install Qt (Windows) - uses: jurplel/install-qt-action@v4.3.1 - if: runner.os == 'Windows' - with: - version: '6.10.3' # aqt has bug with latest qt versions in windows - target: 'desktop' - arch: 'win64_mingw' - cache: true - tools: 'tools_mingw1310' - aqtversion: ==3.3.* - - - name: Install Qt (Linux) - uses: jurplel/install-qt-action@v4.3.1 - if: runner.os == 'Linux' - with: - version: '6.12.0' - target: 'desktop' - arch: 'linux_gcc_64' - cache: true - aqtversion: ==3.3.* - - - name: Install Qt (macOS) - uses: jurplel/install-qt-action@v4.3.1 - if: runner.os == 'macOS' - with: - version: '6.10.3' - target: 'desktop' - arch: 'clang_64' - cache: true - aqtversion: ==3.3.* + # The project is plain C (no Qt code), so no Qt installation is + # required: the CMake project (submodule/CMake/QuasarApp.cmake) only + # looks qmake up at configure time and continues if it is not found. + # Linux and macOS use the pre-installed gcc/clang, Windows the MinGW + # gcc installed from MSYS2 below (same setup as ci.yml). - name: Checkout uses: actions/checkout@v4 @@ -87,19 +59,22 @@ jobs: sudo apt-get update sudo apt-get install -y libpng-dev - # The aqt MinGW does not ship libpng, so install the MinGW libpng from - # MSYS2 and point CMake at it (same setup as ci.yml). - - name: Install libpng (Windows) + # The MinGW gcc compiler (mingw-w64-x86_64-gcc) and the MinGW libpng + # are installed from MSYS2 and CMake is pointed at the msys2 mingw64 + # root (see the Windows configure step, same setup as ci.yml). + - name: Install MinGW gcc and libpng (Windows) id: msys2 if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 with: msystem: MINGW64 - install: mingw-w64-x86_64-libpng + install: mingw-w64-x86_64-gcc mingw-w64-x86_64-libpng + suppress-deprecation-warnings: msystem-mingw64 - # setup-msys2 only adds the MSYS2 root to the Windows PATH, so the - # compiled binaries would not find libpng16-16.dll (and libz-1.dll) at - # runtime and fail with 0xc0000135 (STATUS_DLL_NOT_FOUND). + # setup-msys2 only adds the MSYS2 root to the Windows PATH, so the gcc + # compiler (the configure step) and the compiled binaries (libpng16-16.dll + # and libz-1.dll at runtime) would not be found and fail with 0xc0000135 + # (STATUS_DLL_NOT_FOUND). - name: Add MSYS2 mingw64 bin to PATH (Windows) if: runner.os == 'Windows' run: | @@ -124,7 +99,6 @@ jobs: cmake -B ${{ github.workspace }}/build -G Ninja -DCMAKE_BUILD_TYPE=Release - -DCMAKE_PREFIX_PATH=${{ env.QT_ROOT_DIR }} -S ${{ github.workspace }} - name: Build