diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index bfa6f717..58e0d4cb 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -29,53 +29,61 @@ strategy: VM_IMAGE: 'ubuntu-20.04' APT_PACKAGES: ninja-build g++-8 CXX_COMPILER: g++-8 - RUN_TESTS: true Linux i686 GCC: VM_IMAGE: 'ubuntu-20.04' APT_PACKAGES: ninja-build g++-i686-linux-gnu CXX_COMPILER: i686-linux-gnu-g++ - RUN_TESTS: true Linux arm64 GCC: VM_IMAGE: 'ubuntu-20.04' - APT_PACKAGES: ninja-build g++-aarch64-linux-gnu + APT_PACKAGES: ninja-build g++-aarch64-linux-gnu qemu-user CXX_COMPILER: aarch64-linux-gnu-g++ + CRUNCH_EXE_RUNNER: qemu-aarch64 -L /usr/aarch64-linux-gnu Linux armhf GCC: VM_IMAGE: 'ubuntu-20.04' - APT_PACKAGES: ninja-build g++-arm-linux-gnueabihf + APT_PACKAGES: ninja-build g++-arm-linux-gnueabihf qemu-user CXX_COMPILER: arm-linux-gnueabihf-g++ + CRUNCH_EXE_RUNNER: qemu-arm -L /usr/arm-linux-gnueabihf + # There is a qemu-arm IO bug in ubuntu-20.04 and ubuntu-22.04, + # remove when ubuntu-24.04 is available. + CRUNCH_SIMPLE_TEST: true Linux amd64 Clang: VM_IMAGE: 'ubuntu-20.04' APT_PACKAGES: ninja-build CXX_COMPILER: clang++ - RUN_TESTS: true Windows amd64 MinGW: - VM_IMAGE: 'ubuntu-20.04' - APT_PACKAGES: ninja-build g++-mingw-w64-x86-64 mingw-w64-x86-64-dev + VM_IMAGE: 'ubuntu-22.04' + APT_PACKAGES: ninja-build g++-mingw-w64-x86-64 mingw-w64-x86-64-dev gcc-mingw-w64-x86-64-posix-runtime wine SETUP_COMMANDS: sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix TOOLCHAIN_FILE: cmake/cross-toolchain-mingw64.cmake - EXE_EXTENSIONS: .exe + CRUNCH_EXE_RUNNER: wine + CRUNCH_EXTENSION: .exe + RUNTIME_FILES: /usr/lib/gcc/x86_64-w64-mingw32/10-posix/libgcc_s_seh-1.dll /usr/lib/gcc/x86_64-w64-mingw32/10-posix/libstdc++-6.dll /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll Windows i686 MinGW: - VM_IMAGE: 'ubuntu-20.04' - APT_PACKAGES: ninja-build g++-mingw-w64-i686 mingw-w64-i686-dev + VM_IMAGE: 'ubuntu-22.04' + APT_ARCHITECTURE: i386 + APT_PACKAGES: ninja-build g++-mingw-w64-i686 mingw-w64-i686-dev gcc-mingw-w64-i686-posix-runtime wine wine32 SETUP_COMMANDS: sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix TOOLCHAIN_FILE: cmake/cross-toolchain-mingw32.cmake - EXE_EXTENSIONS: .exe + CRUNCH_EXE_RUNNER: wine + CRUNCH_EXTENSION: .exe + RUNTIME_FILES: /usr/lib/gcc/i686-w64-mingw32/10-posix/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/10-posix/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll macOS amd64 AppleClang: VM_IMAGE: 'macOS-12' CMAKE_GENERATOR: Unix Makefiles NPROC_COMMAND: sysctl -n hw.logicalcpu - RUN_TESTS: true macOS arm64 AppleClang: VM_IMAGE: 'macOS-12' CMAKE_GENERATOR: Unix Makefiles COMPILER_FLAGS: -target arm64-apple-macos11 -Wno-overriding-t-option NPROC_COMMAND: sysctl -n hw.logicalcpu + RUN_TESTS: false Web Asm.js Emscripten: VM_IMAGE: 'ubuntu-22.04' APT_PACKAGES: ninja-build emscripten TOOLCHAIN_FILE: /usr/share/emscripten/cmake/Modules/Platform/Emscripten.cmake SOURCE_DIR: emscripten - EXE_EXTENSIONS: .js .wasm + EXECUTABLES: crunch.js crunch.wasm + RUN_TESTS: false pool: vmImage: $(VM_IMAGE) @@ -83,6 +91,9 @@ pool: steps: - bash: | set -xue + if [ -n "${APT_ARCHITECTURE:-}" ]; then + sudo dpkg --add-architecture "${APT_ARCHITECTURE}" + fi if [ -n "${APT_PACKAGES:-}" ]; then sudo apt-get update && sudo apt-get -y -q --no-install-recommends install ${APT_PACKAGES} fi @@ -112,14 +123,14 @@ steps: displayName: 'Build' - bash: | set -xue - if [ -z "${EXE_EXTENSIONS:-}" ]; then - file 'build/crunch' - else - for ext in ${EXE_EXTENSIONS}; do - file "build/crunch${ext}" - done + EXECUTABLES="${EXECUTABLES:-crunch example1 example2 example3}" + for exe_file in ${EXECUTABLES}; do + file 'build/${exe_file}${CRUNCH_EXTENSION:-}' + done + if [ -n "${RUNTIME_FILES:-}" ]; then + cp -av ${RUNTIME_FILES} build/ fi - if "${RUN_TESTS:-false}"; then + if "${RUN_TESTS:-true}"; then test/test.py fi displayName: 'Test' diff --git a/crnlib/crn_strutils.cpp b/crnlib/crn_strutils.cpp index 8801d1d6..e12504b3 100644 --- a/crnlib/crn_strutils.cpp +++ b/crnlib/crn_strutils.cpp @@ -16,7 +16,7 @@ char* crn_strdup(const char* pStr) { return p; } -char* strcpy_safe(char* pDst, uint dst_len, const char* pSrc) { +char* strcpy_safe(char* pDst, size_t dst_len, const char* pSrc) { CRNLIB_ASSERT(pDst && pSrc && dst_len); if (!dst_len) return pDst; diff --git a/crnlib/crn_strutils.h b/crnlib/crn_strutils.h index def3d329..29593ec4 100644 --- a/crnlib/crn_strutils.h +++ b/crnlib/crn_strutils.h @@ -11,7 +11,7 @@ namespace crnlib { char* crn_strdup(const char* pStr); -char* strcpy_safe(char* pDst, uint dst_len, const char* pSrc); +char* strcpy_safe(char* pDst, size_t dst_len, const char* pSrc); bool int_to_string(int value, char* pDst, uint len); bool uint_to_string(uint value, char* pDst, uint len); diff --git a/example1/example1.cpp b/example1/example1.cpp index 22bbcdc9..ac5b3036 100644 --- a/example1/example1.cpp +++ b/example1/example1.cpp @@ -19,7 +19,9 @@ // .DDS file format definitions. #include "dds_defs.h" -#include "crn_platform.h" +#include "crn_core.h" +#include "crn_strutils.h" +#include "crn_file_utils.h" // stb_image, for loading/saving image files. #ifdef _MSC_VER @@ -141,7 +143,7 @@ static bool print_crn_info(const crn_uint8* pData, crn_uint32 data_size) { if (!crnd::crnd_get_texture_info(pData, data_size, &tex_info)) return false; - printf("Dimensions: %ux%u\nLevels: %u\nFaces: %u\nBytesPerBlock: %u\nUserData0: %u\nUserData1: %u\nCrnFormat: %S\n", + printf("Dimensions: %ux%u\nLevels: %u\nFaces: %u\nBytesPerBlock: %u\nUserData0: %u\nUserData1: %u\nCrnFormat: %s\n", tex_info.m_width, tex_info.m_height, tex_info.m_levels, tex_info.m_faces, tex_info.m_bytes_per_block, tex_info.m_userdata0, tex_info.m_userdata1, crn_get_format_string(tex_info.m_format)); return true; @@ -170,7 +172,7 @@ static bool print_dds_info(const void* pData, crn_uint32 data_size) { "DDSD_TEXTURESTAGE", "DDSD_FVF", "DDSD_SRCVBHANDLE", "DDSD_DEPTH"}; printf("DDSD Flags: 0x%08X ", desc.dwFlags); - for (int i = 0; i < sizeof(pDDSDFlagNames) / sizeof(pDDSDFlagNames[0]); i++) + for (size_t i = 0; i < sizeof(pDDSDFlagNames) / sizeof(pDDSDFlagNames[0]); i++) if ((pDDSDFlagNames[i]) && (desc.dwFlags & (1 << i))) printf("%s ", pDDSDFlagNames[i]); printf("\n\n"); @@ -227,7 +229,7 @@ static bool print_dds_info(const void* pData, crn_uint32 data_size) { "DDSCAPS2_CUBEMAP_POSITIVEY", "DDSCAPS2_CUBEMAP_NEGATIVEY", "DDSCAPS2_CUBEMAP_POSITIVEZ", "DDSCAPS2_CUBEMAP_NEGATIVEZ", NULL, NULL, NULL, NULL, NULL, "DDSCAPS2_VOLUME"}; - for (int i = 0; i < sizeof(pDDCAPS2FlagNames) / sizeof(pDDCAPS2FlagNames[0]); i++) + for (size_t i = 0; i < sizeof(pDDCAPS2FlagNames) / sizeof(pDDCAPS2FlagNames[0]); i++) if ((pDDCAPS2FlagNames[i]) && (desc.ddsCaps.dwCaps2 & (1 << i))) printf("%s ", pDDCAPS2FlagNames[i]); printf("\n"); @@ -312,11 +314,7 @@ int main(int argc, char* argv[]) { if (++i >= argc) return error("Expected output filename!"); -#if defined(_WIN32) - strcpy_s(out_filename, sizeof(out_filename), argv[i]); -#else - strncpy(out_filename, argv[i], sizeof(out_filename)); -#endif + strcpy_safe(out_filename, sizeof(out_filename), argv[i]); } else if (!crnlib_stricmp(argv[i], "-nonsrgb")) srgb_colorspace = false; else if (!crnlib_stricmp(argv[i], "-nomips")) @@ -332,24 +330,10 @@ int main(int argc, char* argv[]) { } // Split the source filename into its various components. -#if defined(_WIN32) - char drive_buf[_MAX_DRIVE], dir_buf[_MAX_DIR], fname_buf[_MAX_FNAME], ext_buf[_MAX_EXT]; - if (_splitpath_s(pSrc_filename, drive_buf, _MAX_DRIVE, dir_buf, _MAX_DIR, fname_buf, _MAX_FNAME, ext_buf, _MAX_EXT)) + dynamic_string drive, dir, fname, ext; + + if (!file_utils::split_path(pSrc_filename, &drive, &dir, &fname, &ext)) return error("Invalid source filename!\n"); -#else - char in_filename[FILENAME_MAX]; - strncpy(in_filename, pSrc_filename, FILENAME_MAX); - const char drive_buf[] = ""; - char *dir_buf = dirname(in_filename); - char *fname_buf = basename(in_filename); - char *dot = strrchr(fname_buf, '.'); - char ext_buf[FILENAME_MAX]; - ext_buf[0] = '\0'; - if (dot && dot != fname_buf) { - strncpy(ext_buf, dot, strlen(dot)); - *dot = '\0'; - } -#endif // Load the source file into memory. printf("Loading source file: %s\n", pSrc_filename); @@ -360,12 +344,12 @@ int main(int argc, char* argv[]) { if (mode == 'i') { // Information - if (crnlib_stricmp(ext_buf, ".crn") == 0) { + if (crnlib_stricmp(ext.get_ptr(), ".crn") == 0) { if (!print_crn_info(pSrc_file_data, src_file_size)) { free(pSrc_file_data); return error("Not a CRN file!\n"); } - } else if (crnlib_stricmp(ext_buf, ".dds") == 0) { + } else if (crnlib_stricmp(ext.get_ptr(), ".dds") == 0) { if (!print_dds_info(pSrc_file_data, src_file_size)) { free(pSrc_file_data); return error("Not a DDS file!\n"); @@ -387,22 +371,13 @@ int main(int argc, char* argv[]) { // If the user has explicitly specified an output file, check the output file's extension to ensure we write the expected format. if (out_filename[0]) { -#if defined(_WIN32) - char out_fname_buf[_MAX_FNAME], out_ext_buf[_MAX_EXT]; - _splitpath_s(out_filename, NULL, 0, NULL, 0, out_fname_buf, _MAX_FNAME, out_ext_buf, _MAX_EXT); -#else - char *out_fname_buf = basename( in_filename ); - dot = strrchr(out_fname_buf, '.'); - char out_ext_buf[FILENAME_MAX]; - out_ext_buf[0] = '\0'; - if (dot && dot != fname_buf) { - strncpy(out_ext_buf, dot, strlen(dot)); - *dot = '\0'; - } -#endif - if (!crnlib_stricmp(out_ext_buf, ".crn")) + dynamic_string out_fname, out_ext; + + file_utils::split_path(out_filename, NULL, NULL, &out_fname, &out_ext); + + if (!crnlib_stricmp(out_ext.get_ptr(), ".crn")) output_crn = true; - else if (!crnlib_stricmp(out_ext_buf, ".dds")) + else if (!crnlib_stricmp(out_ext.get_ptr(), ".dds")) output_crn = false; } @@ -463,17 +438,17 @@ int main(int argc, char* argv[]) { } // Determine the # of helper threads (in addition to the main thread) to use during compression. NumberOfCPU's-1 is reasonable. - int num_helper_threads = 1; + int number_of_processors = 1; #if defined(_WIN32) SYSTEM_INFO g_system_info; GetSystemInfo(&g_system_info); - num_helper_threads = std::max(0, (int)g_system_info.dwNumberOfProcessors - 1); + number_of_processors = std::max(1, (int)g_system_info.dwNumberOfProcessors); #elif defined(__FreeBSD__) || defined(__APPLE__) - num_helper_threads = std::max(1, sysconf(_SC_NPROCESSORS_ONLN)); + number_of_processors = std::max(1, sysconf(_SC_NPROCESSORS_ONLN)); #elif defined(__GNUC__) - num_helper_threads = std::max(1, get_nprocs()); + number_of_processors = std::max(1, get_nprocs()); #endif - comp_params.m_num_helper_threads = num_helper_threads; + comp_params.m_num_helper_threads = std::min(number_of_processors - 1, (int)cCRNMaxHelperThreads); comp_params.m_pProgress_func = progress_callback_func; @@ -502,17 +477,13 @@ int main(int argc, char* argv[]) { // Write the output file. char dst_filename[FILENAME_MAX]; - crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s%s", drive_buf, dir_buf, fname_buf, output_crn ? ".crn" : ".dds"); + crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s%s", drive.get_ptr(), dir.get_ptr(), fname.get_ptr(), output_crn ? ".crn" : ".dds"); if (out_filename[0]) -#if defined(_WIN32) - strcpy_s(dst_filename, sizeof(dst_filename), out_filename); -#else - strncpy(dst_filename, out_filename, sizeof(dst_filename)); -#endif + strcpy_safe(dst_filename, sizeof(dst_filename), out_filename); printf("Writing %s file: %s\n", output_crn ? "CRN" : "DDS", dst_filename); FILE* pFile = NULL; - crn_fopen(&pFile, dst_filename, "wb"); + crn_fopen(&pFile, dst_filename, "wb"); if ((!pFile) || (fwrite(pOutput_file_data, output_file_size, 1, pFile) != 1) || (fclose(pFile) == EOF)) { free(pSrc_file_data); crn_free_block(pOutput_file_data); @@ -522,7 +493,7 @@ int main(int argc, char* argv[]) { crn_free_block(pOutput_file_data); stbi_image_free(pSrc_image); - } else if (crnlib_stricmp(ext_buf, ".crn") == 0) { + } else if (crnlib_stricmp(ext.get_ptr(), ".crn") == 0) { // Decompress/transcode CRN to DDS. printf("Decompressing CRN to DDS\n"); @@ -536,17 +507,13 @@ int main(int argc, char* argv[]) { // Now write the DDS file to disk. char dst_filename[FILENAME_MAX]; - crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s.dds", drive_buf, dir_buf, fname_buf); + crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s.dds", drive.get_ptr(), dir.get_ptr(), fname.get_ptr()); if (out_filename[0]) -#if defined(_WIN32) - strcpy_s(dst_filename, sizeof(dst_filename), out_filename); -#else - strncpy(dst_filename, out_filename, sizeof(dst_filename)); -#endif + strcpy_safe(dst_filename, sizeof(dst_filename), out_filename); printf("Writing file: %s\n", dst_filename); FILE* pFile = NULL; - crn_fopen(&pFile, dst_filename, "wb"); + crn_fopen(&pFile, dst_filename, "wb"); if ((!pFile) || (fwrite(pDDS_file_data, dds_file_size, 1, pFile) != 1) || (fclose(pFile) == EOF)) { crn_free_block(pDDS_file_data); free(pSrc_file_data); @@ -558,22 +525,10 @@ int main(int argc, char* argv[]) { print_dds_info(pDDS_file_data, dds_file_size); crn_free_block(pDDS_file_data); - } else if (crnlib_stricmp(ext_buf, ".dds") == 0) { + } else if (crnlib_stricmp(ext.get_ptr(), ".dds") == 0) { // Unpack DDS to one or more TGA's. if (out_filename[0]) { -#if defined(_WIN32) - _splitpath_s(out_filename, drive_buf, _MAX_DRIVE, dir_buf, _MAX_DIR, fname_buf, _MAX_FNAME, ext_buf, _MAX_EXT); -#else - dir_buf = dirname(out_filename); - fname_buf = basename(out_filename); - dot = strrchr(fname_buf, '.'); - ext_buf[FILENAME_MAX]; - ext_buf[0] = '\0'; - if (dot && dot != fname_buf) { - strncpy(ext_buf, dot, strlen(dot)); - *dot = '\0'; - } -#endif + file_utils::split_path(out_filename, &drive, &dir, &fname, &ext); } crn_texture_desc tex_desc; @@ -596,7 +551,7 @@ int main(int argc, char* argv[]) { int height = std::max(1U, tex_desc.m_height >> level_index); char dst_filename[FILENAME_MAX]; - crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s_face%u_mip%u.tga", drive_buf, dir_buf, fname_buf, face_index, level_index); + crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s_face%u_mip%u.tga", drive.get_ptr(), dir.get_ptr(), fname.get_ptr(), face_index, level_index); printf("Writing file: %s\n", dst_filename); if (!stbi_write_tga(dst_filename, width, height, 4, pImages[level_index + face_index * tex_desc.m_levels])) { diff --git a/example2/example2.cpp b/example2/example2.cpp index 7d2c462e..910a9b4c 100644 --- a/example2/example2.cpp +++ b/example2/example2.cpp @@ -28,6 +28,12 @@ using namespace crnlib; +#if defined(_WIN32) +#define example2_strcpy_safe(d, l, s) strcpy_s(d, l, s) +#else +void example2_strcpy_safe(char *d, size_t l, const char* s) {l = strnlen(s, l - 1); memcpy(d, s, l); d[l] = '\0';} +#endif + static int print_usage() { printf("Description: Transcodes .CRN to .DDS files using crn_decomp.h.\n"); printf("Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC\n"); @@ -90,11 +96,7 @@ int main(int argc, char* argv[]) { if (++i >= argc) return error("Expected output filename!"); -#if defined(_WIN32) - strcpy_s(out_filename, sizeof(out_filename), argv[i]); -#else - strncpy(out_filename, argv[i], sizeof(out_filename)); -#endif + example2_strcpy_safe(out_filename, sizeof(out_filename), argv[i]); } else return error("Invalid option: %s\n", argv[i]); } @@ -137,7 +139,7 @@ int main(int argc, char* argv[]) { // Now create the DDS file. char dst_filename[FILENAME_MAX]; if (out_filename[0]) { - strcpy(dst_filename, out_filename); + example2_strcpy_safe(dst_filename, sizeof(dst_filename), out_filename); } else { unsigned int stripped_length = UINT32_MAX; const char* ext_begin = strrchr(pSrc_filename, '.'); diff --git a/example3/example3.cpp b/example3/example3.cpp index 80189b49..2149cbd0 100644 --- a/example3/example3.cpp +++ b/example3/example3.cpp @@ -18,7 +18,9 @@ // .DDS file format definitions. #include "dds_defs.h" -#include "crn_platform.h" +#include "crn_core.h" +#include "crn_strutils.h" +#include "crn_file_utils.h" // stb_image, for loading/saving image files. #ifdef _MSC_VER @@ -93,11 +95,7 @@ int main(int argc, char* argv[]) { if (++i >= argc) return error("Expected output filename!"); -#if defined(_WIN32) - strcpy_s(out_filename, sizeof(out_filename), argv[i]); -#else - strncpy(out_filename, argv[i], sizeof(out_filename)); -#endif + strcpy_safe(out_filename, sizeof(out_filename), argv[i]); } else if (!crnlib_stricmp(argv[i], "-nonsrgb")) srgb_colorspace = false; else if (!crnlib_stricmp(argv[i], "-pixelformat")) { @@ -136,20 +134,9 @@ int main(int argc, char* argv[]) { } // Split the source filename into its various components. -#if defined(_WIN32) - char drive_buf[_MAX_DRIVE], dir_buf[_MAX_DIR], fname_buf[_MAX_FNAME], ext_buf[_MAX_EXT]; - if (_splitpath_s(pSrc_filename, drive_buf, _MAX_DRIVE, dir_buf, _MAX_DIR, fname_buf, _MAX_FNAME, ext_buf, _MAX_EXT)) + dynamic_string drive, dir, fname, ext; + if (!file_utils::split_path(pSrc_filename, &drive, &dir, &fname, &ext)) return error("Invalid source filename!\n"); -#else - char in_filename[FILENAME_MAX]; - strncpy(in_filename, pSrc_filename, FILENAME_MAX); - const char drive_buf[] = ""; - char *dir_buf = dirname(in_filename); - char *fname_buf = basename(in_filename); - char *dot = strrchr(fname_buf, '.'); - if (dot && dot != fname_buf) - *dot = '\0'; -#endif // Load the source image into memory. printf("Loading source file: %s\n", pSrc_filename); @@ -215,9 +202,9 @@ int main(int argc, char* argv[]) { // Exact block from image, clamping at the sides of non-divisible by 4 images to avoid artifacts. crn_uint32* pDst_pixels = pixels; - for (int y = 0; y < cDXTBlockSize; y++) { + for (uint y = 0; y < cDXTBlockSize; y++) { const uint actual_y = std::min(height - 1U, (block_y * cDXTBlockSize) + y); - for (int x = 0; x < cDXTBlockSize; x++) { + for (uint x = 0; x < cDXTBlockSize; x++) { const uint actual_x = std::min(width - 1U, (block_x * cDXTBlockSize) + x); *pDst_pixels++ = pSrc_image[actual_x + actual_y * width]; } @@ -241,13 +228,9 @@ int main(int argc, char* argv[]) { // Now create the DDS file. char dst_filename[FILENAME_MAX]; - crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s.dds", drive_buf, dir_buf, fname_buf); + crnlib_snprintf(dst_filename, sizeof(dst_filename), "%s%s%s.dds", drive.get_ptr(), dir.get_ptr(), fname.get_ptr()); if (out_filename[0]) -#if defined(_WIN32) - strcpy_s(dst_filename, sizeof(dst_filename), out_filename); -#else - strncpy(dst_filename, out_filename, sizeof(dst_filename)); -#endif + strcpy_safe(dst_filename, sizeof(dst_filename), out_filename); printf("Writing DDS file: %s\n", dst_filename); diff --git a/test/test.py b/test/test.py index 78a9b760..b560f354 100755 --- a/test/test.py +++ b/test/test.py @@ -4,32 +4,44 @@ import subprocess import sys +build_dir = os.getenv("CRUNCH_BUILD_DIR", "build") +executable_extension = os.getenv("CRUNCH_EXE_EXTENSION", "") +executable_runner = os.getenv("CRUNCH_EXE_RUNNER") + def print_command(command_list): print("running: " + " ".join(command_list), file=sys.stderr) def convert_path(path): + if path.startswith("build/"): + path = build_dir + path[len("build"):] return path.replace("/", os.path.sep) def run(command_list): + if executable_runner: + command_list = executable_runner.split(" ") + command_list print_command(command_list) returncode = subprocess.run(command_list).returncode if returncode: exit(returncode) def mkdir(path): + path = convert_path(path) print_command(["mkdir", path]) os.makedirs(path, exist_ok=True) -def crunch(input_path, output_path, options=[]): - executable_extension = ["", ".exe"][sys.platform == 'win32'] - executable_name = "crunch" + executable_extension - - build_dir = "build" +def get_build_dir(): windows_build_dir = os.path.join(build_dir, "Release") if os.path.exists(windows_build_dir): - build_dir = windows_build_dir + return windows_build_dir + return build_dir - executable_path = os.path.join(build_dir, executable_name) +def get_executable_path(executable_name): + executable_name += executable_extension + build_dir = get_build_dir() + return os.path.join(build_dir, executable_name) + +def crunch(input_path, output_path, options=[]): + executable_path = get_executable_path("crunch") command_list = [executable_path] + options if input_path: @@ -39,8 +51,31 @@ def crunch(input_path, output_path, options=[]): run(command_list) +def example(num, input_path, output_path, options=[]): + executable_path = get_executable_path("example" + str(num)) + command_list = [executable_path] + + if (num == 1): + command_list += [options[0]] + options = options[1:] + + if input_path: + input_path = convert_path(input_path) + command_list += [input_path] + + command_list += options + + if output_path: + output_path = convert_path(output_path) + command_list += ["-out", output_path] + + run(command_list) + crunch(None, None, ["--help"]) +if "CRUNCH_SIMPLE_TEST" in os.environ.keys(): + exit(0) + mkdir("build/test/0") crunch("test/unvanquished_64.png", "build/test/0/unvanquished_64.crn") crunch("test/unvanquished_64.png", "build/test/0/unvanquished_64.dds") @@ -99,3 +134,17 @@ def crunch(input_path, output_path, options=[]): mkdir("build/test/7") crunch("test/black.jpg", "build/test/7/black.crn") + +mkdir("build/test/8") +example(1, "test/unvanquished_64.png", None, ["i"]) +example(1, "test/unvanquished_64.png", "build/test/8/unvanquished_64.dds", ["c"]) + +mkdir("build/test/9") +example(1, "test/unvanquished_64.png", "build/test/9/unvanquished_64.crn", ["c", "-crn"]) +example(1, "build/test/9/unvanquished_64.crn", "build/test/9/unvanquished_64.dds", ["d"]) + +mkdir("build/test/10") +example(2, "build/test/9/unvanquished_64.crn", "build/test/10/unvanquished_64.dds") + +mkdir("build/test/11") +example(3, "test/unvanquished_64.png", "build/test/11/unvanquished_64.dds")