mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-06 18:56:54 +08:00
[cpp] Fix double free crash in SkeletonBinary::readSkeletonDataFile, add terminal logging utilities and style guide, add nostdcpp
This commit is contained in:
parent
aaca02ad81
commit
2036aa3e76
3
.gitignore
vendored
3
.gitignore
vendored
@ -254,3 +254,6 @@ spine-c/codegen/spine-cpp-types.json
|
|||||||
spine-flutter/example/devtools_options.yaml
|
spine-flutter/example/devtools_options.yaml
|
||||||
spine-glfw/.cache
|
spine-glfw/.cache
|
||||||
formatters/eclipse-formatter/format-diff.txt
|
formatters/eclipse-formatter/format-diff.txt
|
||||||
|
spine-cpp/build-debug
|
||||||
|
spine-cpp/build-linux
|
||||||
|
spine-cpp/build-release-debug
|
||||||
|
|||||||
93
formatters/logging/bash-colors.sh
Normal file
93
formatters/logging/bash-colors.sh
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Bash color and formatting utilities
|
||||||
|
# Source this file in your bash scripts for colored output
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
MAGENTA='\033[0;35m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
WHITE='\033[0;37m'
|
||||||
|
GRAY='\033[0;90m'
|
||||||
|
|
||||||
|
# Bright colors
|
||||||
|
BRIGHT_RED='\033[0;91m'
|
||||||
|
BRIGHT_GREEN='\033[0;92m'
|
||||||
|
BRIGHT_YELLOW='\033[0;93m'
|
||||||
|
BRIGHT_BLUE='\033[0;94m'
|
||||||
|
BRIGHT_MAGENTA='\033[0;95m'
|
||||||
|
BRIGHT_CYAN='\033[0;96m'
|
||||||
|
BRIGHT_WHITE='\033[0;97m'
|
||||||
|
|
||||||
|
# Background colors
|
||||||
|
BG_RED='\033[41m'
|
||||||
|
BG_GREEN='\033[42m'
|
||||||
|
BG_YELLOW='\033[43m'
|
||||||
|
BG_BLUE='\033[44m'
|
||||||
|
BG_MAGENTA='\033[45m'
|
||||||
|
BG_CYAN='\033[46m'
|
||||||
|
BG_WHITE='\033[47m'
|
||||||
|
|
||||||
|
# Text styles
|
||||||
|
BOLD='\033[1m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
UNDERLINE='\033[4m'
|
||||||
|
BLINK='\033[5m'
|
||||||
|
REVERSE='\033[7m'
|
||||||
|
STRIKETHROUGH='\033[9m'
|
||||||
|
|
||||||
|
# Reset
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Design principles:
|
||||||
|
# 1. Minimal visual noise - use color sparingly for emphasis
|
||||||
|
# 2. Clear hierarchy - different levels of information have different treatments
|
||||||
|
# 3. Consistent spacing - clean vertical rhythm
|
||||||
|
# 4. Accessible - readable without colors
|
||||||
|
|
||||||
|
# Main header for script/tool name
|
||||||
|
log_title() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}$1${NC}"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Section headers for major phases
|
||||||
|
log_section() {
|
||||||
|
echo -e "${BOLD}${BLUE}$1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Individual actions/steps
|
||||||
|
log_action() {
|
||||||
|
echo -e " $1..."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Results - success/failure/info
|
||||||
|
log_ok() {
|
||||||
|
echo -e " ${GREEN}✓${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_fail() {
|
||||||
|
echo -e " ${RED}✗${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warn() {
|
||||||
|
echo -e " ${YELLOW}!${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_skip() {
|
||||||
|
echo -e " ${GRAY}-${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Final summary
|
||||||
|
log_summary() {
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}$1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detailed output (errors, etc.)
|
||||||
|
log_detail() {
|
||||||
|
echo -e "${GRAY}$1${NC}"
|
||||||
|
}
|
||||||
153
formatters/logging/terminal-logging-guide.md
Normal file
153
formatters/logging/terminal-logging-guide.md
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# Terminal Logging Style Guide
|
||||||
|
|
||||||
|
This guide defines the terminal output style for all bash scripts in the Spine Runtimes project.
|
||||||
|
|
||||||
|
## Design Principles
|
||||||
|
|
||||||
|
1. **Minimal visual noise** - Use color sparingly for emphasis, not decoration
|
||||||
|
2. **Clear hierarchy** - Different levels of information have distinct visual treatments
|
||||||
|
3. **Consistent spacing** - Clean vertical rhythm throughout output
|
||||||
|
4. **Accessible** - Readable and meaningful even without colors
|
||||||
|
5. **Scannable** - Easy to quickly identify successes, failures, and important information
|
||||||
|
|
||||||
|
## Visual Hierarchy
|
||||||
|
|
||||||
|
### 1. Title (`log_title`)
|
||||||
|
- **Purpose**: Main script/tool name
|
||||||
|
- **Style**: Bold with vertical spacing
|
||||||
|
- **Usage**: Once at the beginning of script execution
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_title "Spine-C++ Test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Section (`log_section`)
|
||||||
|
- **Purpose**: Major phases or groups of operations
|
||||||
|
- **Style**: Bold blue text, no extra spacing
|
||||||
|
- **Usage**: Build, Test, Deploy, etc.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_section "Build"
|
||||||
|
log_section "Test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Action (`log_action`)
|
||||||
|
- **Purpose**: Individual operations in progress
|
||||||
|
- **Style**: Indented, followed by "..."
|
||||||
|
- **Usage**: Before starting an operation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_action "Building all variants"
|
||||||
|
log_action "Testing headless-test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Results
|
||||||
|
- **Purpose**: Outcome of operations
|
||||||
|
- **Style**: Indented with colored symbols
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_ok "Build completed" # Green ✓
|
||||||
|
log_fail "Build failed" # Red ✗
|
||||||
|
log_warn "Deprecated feature" # Yellow !
|
||||||
|
log_skip "Not supported on macOS" # Gray -
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Detail (`log_detail`)
|
||||||
|
- **Purpose**: Secondary information, error output, debug info
|
||||||
|
- **Style**: Gray text, indented
|
||||||
|
- **Usage**: Additional context, error messages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_detail "Platform: Darwin"
|
||||||
|
log_detail "$ERROR_OUTPUT"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Summary (`log_summary`)
|
||||||
|
- **Purpose**: Final result or conclusion
|
||||||
|
- **Style**: Bold with vertical spacing
|
||||||
|
- **Usage**: End of script execution
|
||||||
|
|
||||||
|
```bash
|
||||||
|
log_summary "✓ All tests passed (5/5)"
|
||||||
|
log_summary "✗ Tests failed (3/5)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
source ../formatters/bash-colors.sh
|
||||||
|
|
||||||
|
log_title "Spine-C++ Test"
|
||||||
|
log_detail "Platform: $(uname)"
|
||||||
|
|
||||||
|
log_section "Build"
|
||||||
|
log_action "Building all variants"
|
||||||
|
if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then
|
||||||
|
log_ok "Build completed"
|
||||||
|
else
|
||||||
|
log_fail "Build failed"
|
||||||
|
log_detail "$BUILD_OUTPUT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_section "Test"
|
||||||
|
log_action "Testing headless-test"
|
||||||
|
if test_result; then
|
||||||
|
log_ok "headless-test"
|
||||||
|
else
|
||||||
|
log_fail "headless-test - execution failed"
|
||||||
|
log_detail "$error_output"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_summary "✓ All tests passed (2/2)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Preview
|
||||||
|
|
||||||
|
```
|
||||||
|
Spine-C++ Test
|
||||||
|
|
||||||
|
Platform: Darwin
|
||||||
|
|
||||||
|
Build
|
||||||
|
Building all variants...
|
||||||
|
✓ Build completed
|
||||||
|
|
||||||
|
Test
|
||||||
|
Testing headless-test...
|
||||||
|
✓ headless-test
|
||||||
|
Testing headless-test-nostdcpp...
|
||||||
|
✓ headless-test-nostdcpp
|
||||||
|
|
||||||
|
✓ All tests passed (2/2)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling Best Practices
|
||||||
|
|
||||||
|
1. **Capture output**: Use `OUTPUT=$(command 2>&1)` to capture both stdout and stderr
|
||||||
|
2. **Check exit codes**: Always check if critical operations succeeded
|
||||||
|
3. **Show details on failure**: Use `log_detail` to show error output
|
||||||
|
4. **Fail fast**: Exit immediately on critical failures
|
||||||
|
5. **Clear error messages**: Make failure reasons obvious
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then
|
||||||
|
log_ok "Build completed"
|
||||||
|
else
|
||||||
|
log_fail "Build failed"
|
||||||
|
log_detail "$BUILD_OUTPUT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Source the utilities in your script:
|
||||||
|
```bash
|
||||||
|
source ../formatters/logging/bash-colors.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Follow the hierarchy patterns shown above
|
||||||
|
3. Use appropriate functions for each type of output
|
||||||
|
4. Test output both with and without color support
|
||||||
@ -7,7 +7,11 @@ option(SPINE_NO_FILE_IO "Disable file I/O operations" OFF)
|
|||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
file(GLOB INCLUDES "include/**/*.h")
|
file(GLOB INCLUDES "include/**/*.h")
|
||||||
file(GLOB SOURCES "src/**/*.cpp")
|
file(GLOB ALL_SOURCES "src/**/*.cpp")
|
||||||
|
|
||||||
|
# Exclude nostdcpp.cpp from regular build
|
||||||
|
list(FILTER ALL_SOURCES EXCLUDE REGEX "src/nostdcpp\\.cpp$")
|
||||||
|
set(SOURCES ${ALL_SOURCES})
|
||||||
|
|
||||||
add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES})
|
add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES})
|
||||||
target_include_directories(spine-cpp PUBLIC include)
|
target_include_directories(spine-cpp PUBLIC include)
|
||||||
@ -17,7 +21,7 @@ if(SPINE_NO_FILE_IO)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# nostdcpp variant (no C++ standard library)
|
# nostdcpp variant (no C++ standard library)
|
||||||
file(GLOB NOSTDCPP_SOURCES ${SOURCES} "src/nostdlib.cpp")
|
set(NOSTDCPP_SOURCES ${SOURCES} "src/nostdcpp.cpp")
|
||||||
add_library(spine-cpp-nostdcpp STATIC ${NOSTDCPP_SOURCES} ${INCLUDES})
|
add_library(spine-cpp-nostdcpp STATIC ${NOSTDCPP_SOURCES} ${INCLUDES})
|
||||||
target_include_directories(spine-cpp-nostdcpp PUBLIC include)
|
target_include_directories(spine-cpp-nostdcpp PUBLIC include)
|
||||||
|
|
||||||
@ -35,28 +39,39 @@ export(
|
|||||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||||
add_executable(headless-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
add_executable(headless-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
||||||
target_link_libraries(headless-test spine-cpp)
|
target_link_libraries(headless-test spine-cpp)
|
||||||
|
|
||||||
if(SPINE_NO_FILE_IO)
|
if(SPINE_NO_FILE_IO)
|
||||||
target_compile_definitions(headless-test PRIVATE SPINE_NO_FILE_IO)
|
target_compile_definitions(headless-test PRIVATE SPINE_NO_FILE_IO)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# nostdcpp test executable (no C++ stdlib)
|
# Configure nostdcpp linking for different platforms
|
||||||
add_executable(headless-test-nostdcpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
add_executable(headless-test-nostdcpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
||||||
|
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# On Windows/MSVC, disable default libraries but keep C runtime
|
|
||||||
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
|
|
||||||
target_link_options(headless-test-nostdcpp PRIVATE /NODEFAULTLIB)
|
target_link_options(headless-test-nostdcpp PRIVATE /NODEFAULTLIB)
|
||||||
target_link_libraries(headless-test-nostdcpp msvcrt kernel32)
|
target_link_libraries(headless-test-nostdcpp msvcrt kernel32)
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
target_link_options(headless-test-nostdcpp PRIVATE -nostdlib++ -lc)
|
||||||
else()
|
else()
|
||||||
# Unix/Linux: avoid linking libstdc++ automatically
|
target_link_options(headless-test-nostdcpp PRIVATE -nodefaultlibs)
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
target_link_libraries(headless-test-nostdcpp -lm -lc -lgcc)
|
||||||
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp)
|
endif()
|
||||||
target_link_options(headless-test-nostdcpp PRIVATE -nostdlib++ -lc)
|
|
||||||
else()
|
# Static variants (Linux only)
|
||||||
# GCC: use -nodefaultlibs and link minimal libraries including libgcc for operator new/delete
|
if(UNIX AND NOT APPLE)
|
||||||
target_link_options(headless-test-nostdcpp PRIVATE -nodefaultlibs)
|
add_executable(headless-test-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
||||||
target_link_libraries(headless-test-nostdcpp spine-cpp-nostdcpp -lm -lc -lgcc)
|
target_link_libraries(headless-test-static spine-cpp)
|
||||||
|
target_link_options(headless-test-static PRIVATE -static)
|
||||||
|
|
||||||
|
add_executable(headless-test-nostdcpp-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
|
||||||
|
target_link_libraries(headless-test-nostdcpp-static spine-cpp-nostdcpp)
|
||||||
|
target_link_options(headless-test-nostdcpp-static PRIVATE -static -static-libgcc -Wl,--exclude-libs,libstdc++.a)
|
||||||
|
target_link_libraries(headless-test-nostdcpp-static -lm -lc)
|
||||||
|
|
||||||
|
if(SPINE_NO_FILE_IO)
|
||||||
|
target_compile_definitions(headless-test-static PRIVATE SPINE_NO_FILE_IO)
|
||||||
|
target_compile_definitions(headless-test-nostdcpp-static PRIVATE SPINE_NO_FILE_IO)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
63
spine-cpp/src/nostdcpp.cpp
Normal file
63
spine-cpp/src/nostdcpp.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated April 5, 2025. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2025, Esoteric Software LLC
|
||||||
|
*
|
||||||
|
* Integration of the Spine Runtimes into software or otherwise creating
|
||||||
|
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||||
|
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||||
|
* http://esotericsoftware.com/spine-editor-license
|
||||||
|
*
|
||||||
|
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||||
|
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||||
|
* "Products"), provided that each user of the Products must obtain their own
|
||||||
|
* Spine Editor license and redistribution of the Products in any form must
|
||||||
|
* include this license and copyright notice.
|
||||||
|
*
|
||||||
|
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||||
|
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
// Stubs for C++ stdlib functions spine-cpp depends on. Used for nostdcpp builds.
|
||||||
|
// These are weak symbols to allow overriding in custom builds, e.g. headless-test-nostdcpp
|
||||||
|
// where the main app still requires C++.
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void* malloc(size_t size);
|
||||||
|
void free(void* ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void* operator new(size_t size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void operator delete(void* ptr) {
|
||||||
|
if (ptr) free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __attribute__((weak)) int __cxa_guard_acquire(char* guard) {
|
||||||
|
return *guard == 0 ? (*guard = 1, 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __attribute__((weak)) void __cxa_guard_release(char* guard) {
|
||||||
|
// No-op for single-threaded
|
||||||
|
(void)guard;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __attribute__((weak)) void __cxa_pure_virtual() {
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __attribute__((weak)) char __stack_chk_guard = 0;
|
||||||
|
extern "C" __attribute__((weak)) void __stack_chk_fail() {
|
||||||
|
}
|
||||||
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minimal runtime stubs for nostdlib spine-cpp build
|
|
||||||
*
|
|
||||||
* Provides minimal implementations of C++ runtime symbols required
|
|
||||||
* for spine-cpp to work without the standard library.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// C++ Runtime Stubs
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
// Memory operators - basic malloc/free wrappers
|
|
||||||
// Note: These require a C library that provides malloc/free
|
|
||||||
extern "C" {
|
|
||||||
void* malloc(size_t size);
|
|
||||||
void free(void* ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory operators - use malloc/free but with careful implementation
|
|
||||||
// Make them weak so system can override if needed
|
|
||||||
__attribute__((weak)) void* operator new(size_t size) {
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) void operator delete(void* ptr) {
|
|
||||||
if (ptr) free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static initialization guards (single-threaded stubs)
|
|
||||||
// Make them weak so system can override if needed
|
|
||||||
extern "C" __attribute__((weak)) int __cxa_guard_acquire(char* guard) {
|
|
||||||
return *guard == 0 ? (*guard = 1, 1) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" __attribute__((weak)) void __cxa_guard_release(char* guard) {
|
|
||||||
// No-op for single-threaded
|
|
||||||
(void)guard;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pure virtual function handler
|
|
||||||
extern "C" __attribute__((weak)) void __cxa_pure_virtual() {
|
|
||||||
// In a real implementation, this would abort or throw
|
|
||||||
// For minimal stub, we'll just return (undefined behavior but won't crash)
|
|
||||||
// This should never be called in a correctly written program
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stack protection (for GCC -fstack-protector)
|
|
||||||
// Make it weak so libc can override it in static builds
|
|
||||||
extern "C" __attribute__((weak)) char __stack_chk_guard = 0;
|
|
||||||
extern "C" __attribute__((weak)) void __stack_chk_fail() {
|
|
||||||
// Could call abort() or be no-op for minimal runtime
|
|
||||||
}
|
|
||||||
@ -118,7 +118,7 @@ SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) {
|
|||||||
const char *lastDot = strrchr(nameWithoutExtension.buffer(), '.');
|
const char *lastDot = strrchr(nameWithoutExtension.buffer(), '.');
|
||||||
if (lastDot) {
|
if (lastDot) {
|
||||||
int length = lastDot - nameWithoutExtension.buffer();
|
int length = lastDot - nameWithoutExtension.buffer();
|
||||||
nameWithoutExtension = String(nameWithoutExtension.buffer(), length);
|
nameWithoutExtension = nameWithoutExtension.substring(0, length);
|
||||||
}
|
}
|
||||||
skeletonData->_name = nameWithoutExtension;
|
skeletonData->_name = nameWithoutExtension;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
# Build or reuse Docker image
|
|
||||||
IMAGE_NAME="spine-cpp-nostdcpp-test"
|
|
||||||
if ! docker image inspect $IMAGE_NAME >/dev/null 2>&1; then
|
|
||||||
echo "Building Docker image (one-time setup)..."
|
|
||||||
docker build -t $IMAGE_NAME - <<'EOF'
|
|
||||||
FROM ubuntu:22.04
|
|
||||||
RUN apt-get update >/dev/null 2>&1 && \
|
|
||||||
apt-get install -y build-essential cmake ninja-build git file >/dev/null 2>&1 && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Running spine-cpp nostdcpp test..."
|
|
||||||
|
|
||||||
# Run Docker container with spine-runtimes directory mounted
|
|
||||||
docker run --rm \
|
|
||||||
-v "$(pwd)/..:/workspace/spine-runtimes" \
|
|
||||||
-w /workspace/spine-runtimes/spine-cpp \
|
|
||||||
$IMAGE_NAME \
|
|
||||||
bash -c "
|
|
||||||
|
|
||||||
# Build everything first
|
|
||||||
echo '=== Building all variants ==='
|
|
||||||
./build.sh clean release >/dev/null 2>&1
|
|
||||||
|
|
||||||
# Try to build static regular executable
|
|
||||||
echo 'Building static regular executable...'
|
|
||||||
g++ -static -o build/headless-test-static build/CMakeFiles/headless-test.dir/tests/HeadlessTest.cpp.o build/libspine-cpp.a >/dev/null 2>&1 || echo 'Static regular build failed'
|
|
||||||
|
|
||||||
# Try to build static nostdcpp executable (multiple approaches)
|
|
||||||
echo 'Building static nostdcpp executable...'
|
|
||||||
|
|
||||||
# Approach 1: Try with -static-libgcc and -static-libstdc++ but no libstdc++
|
|
||||||
if g++ -static -static-libgcc -Wl,--exclude-libs,libstdc++.a -o build/headless-test-nostdcpp-static build/CMakeFiles/headless-test-nostdcpp.dir/tests/HeadlessTest.cpp.o build/libspine-cpp-nostdcpp.a -lm -lc 2>/dev/null; then
|
|
||||||
echo 'SUCCESS: Static nostdcpp built (approach 1)'
|
|
||||||
# Approach 2: Try minimal static linking
|
|
||||||
elif g++ -static -o build/headless-test-nostdcpp-static-minimal build/CMakeFiles/headless-test-nostdcpp.dir/tests/HeadlessTest.cpp.o build/libspine-cpp-nostdcpp.a 2>/dev/null; then
|
|
||||||
echo 'SUCCESS: Static nostdcpp built (approach 2 - minimal)'
|
|
||||||
else
|
|
||||||
echo 'All static nostdcpp approaches failed - static linking may not be practical on this system'
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ''
|
|
||||||
echo '=== FINAL RESULTS ==='
|
|
||||||
echo ''
|
|
||||||
echo 'File sizes:'
|
|
||||||
for exe in build/headless-test*; do
|
|
||||||
if [ -f \"\$exe\" ]; then
|
|
||||||
ls -lah \"\$exe\" | awk '{printf \"%-30s %s\\n\", \$9, \$5}'
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ''
|
|
||||||
echo 'Dependencies:'
|
|
||||||
for exe in build/headless-test*; do
|
|
||||||
if [ -f \"\$exe\" ]; then
|
|
||||||
echo \"\$(basename \$exe):\"
|
|
||||||
ldd \"\$exe\" 2>/dev/null || echo \" (statically linked)\"
|
|
||||||
echo ''
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo 'Functional test:'
|
|
||||||
if [ -f build/headless-test-nostdcpp ]; then
|
|
||||||
echo 'Testing headless-test-nostdcpp with spineboy...'
|
|
||||||
if OUTPUT=\$(./build/headless-test-nostdcpp ../examples/spineboy/export/spineboy-pro.skel ../examples/spineboy/export/spineboy-pma.atlas idle 2>&1); then
|
|
||||||
echo \"\$OUTPUT\" | head -10
|
|
||||||
echo '... (output truncated)'
|
|
||||||
echo 'SUCCESS: nostdcpp executable works!'
|
|
||||||
else
|
|
||||||
echo 'FAILED: nostdcpp executable failed to run'
|
|
||||||
echo \"Error: \$OUTPUT\"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo 'nostdcpp executable not found'
|
|
||||||
fi
|
|
||||||
"
|
|
||||||
89
spine-cpp/tests/test.sh
Executable file
89
spine-cpp/tests/test.sh
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Spine-C++ Smoke Test
|
||||||
|
#
|
||||||
|
# Tests all spine-cpp build variants with spineboy example data:
|
||||||
|
# - headless-test (regular dynamic)
|
||||||
|
# - headless-test-nostdcpp (nostdcpp dynamic)
|
||||||
|
# - headless-test-static (regular static, Linux only)
|
||||||
|
# - headless-test-nostdcpp-static (nostdcpp static, Linux only)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Change to spine-cpp root directory
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
# Source logging utilities
|
||||||
|
source ../formatters/logging/bash-colors.sh
|
||||||
|
|
||||||
|
# Test configuration - spineboy example files and animation
|
||||||
|
SPINEBOY_SKEL="../examples/spineboy/export/spineboy-pro.skel"
|
||||||
|
SPINEBOY_ATLAS="../examples/spineboy/export/spineboy-pma.atlas"
|
||||||
|
SPINEBOY_ANIM="idle"
|
||||||
|
|
||||||
|
# Expected output pattern - first 10 lines of skeleton JSON data
|
||||||
|
EXPECTED_OUTPUT="=== SKELETON DATA ===
|
||||||
|
{
|
||||||
|
\"type\": \"SkeletonData\",
|
||||||
|
\"bones\": [{
|
||||||
|
\"type\": \"BoneData\",
|
||||||
|
\"index\": 0,
|
||||||
|
\"parent\": null,
|
||||||
|
\"length\": 0,
|
||||||
|
\"color\": {
|
||||||
|
\"r\": 0.607843,"
|
||||||
|
|
||||||
|
log_title "Spine-C++ Test"
|
||||||
|
log_detail "Platform: $(uname)"
|
||||||
|
|
||||||
|
log_section "Build"
|
||||||
|
log_action "Building all variants"
|
||||||
|
if BUILD_OUTPUT=$(./build.sh clean release 2>&1); then
|
||||||
|
log_ok "Build completed"
|
||||||
|
else
|
||||||
|
log_fail "Build failed"
|
||||||
|
log_detail "$BUILD_OUTPUT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_section "Test"
|
||||||
|
|
||||||
|
test_count=0
|
||||||
|
pass_count=0
|
||||||
|
|
||||||
|
for exe in build/headless-test*; do
|
||||||
|
if [ -f "$exe" ] && [ -x "$exe" ]; then
|
||||||
|
exe_name=$(basename "$exe")
|
||||||
|
log_action "Testing $exe_name"
|
||||||
|
|
||||||
|
test_count=$((test_count + 1))
|
||||||
|
|
||||||
|
if OUTPUT=$("$exe" $SPINEBOY_SKEL $SPINEBOY_ATLAS $SPINEBOY_ANIM 2>&1); then
|
||||||
|
actual_output=$(echo "$OUTPUT" | head -10)
|
||||||
|
|
||||||
|
if [ "$actual_output" = "$EXPECTED_OUTPUT" ]; then
|
||||||
|
log_ok "$exe_name"
|
||||||
|
pass_count=$((pass_count + 1))
|
||||||
|
else
|
||||||
|
log_fail "$exe_name - output mismatch"
|
||||||
|
log_detail "Expected:"
|
||||||
|
log_detail "$EXPECTED_OUTPUT"
|
||||||
|
log_detail ""
|
||||||
|
log_detail "Actual:"
|
||||||
|
log_detail "$actual_output"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_fail "$exe_name - execution failed"
|
||||||
|
log_detail "$OUTPUT"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $pass_count -eq $test_count ] && [ $test_count -gt 0 ]; then
|
||||||
|
log_summary "✓ All tests passed ($pass_count/$test_count)"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
log_summary "✗ Tests failed ($pass_count/$test_count)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Loading…
x
Reference in New Issue
Block a user