Skip to content

Instantly share code, notes, and snippets.

@scivision
Last active April 17, 2025 02:58
Show Gist options
  • Save scivision/62e822cdf6e35b6858933676e5b98cd5 to your computer and use it in GitHub Desktop.
Save scivision/62e822cdf6e35b6858933676e5b98cd5 to your computer and use it in GitHub Desktop.
CMake execute_process() doesn't print till program ends or stdout is flushed

CMake / CTest console output needs flush

CMake execute_process() and CTest executable runs do not update the console text output until flushed. If the executable exits abnormally, the console output may not appear at all in CMake execute_process() or CTest run.

Build and execute by:

cmake --workflow default
cmake_minimum_required(VERSION 3.12)
project(stdout_buffering LANGUAGES CXX)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
add_executable(print_flush print_flush.cpp)
add_test(NAME print_flush COMMAND print_flush)
find_package(Python COMPONENTS Interpreter)
if(Python_Interpreter_FOUND)
add_test(NAME print_flush_python
COMMAND Python::Interpreter ${CMAKE_CURRENT_SOURCE_DIR}/print_flush.py)
endif()
set_property(TEST print_flush print_flush_python PROPERTY TIMEOUT 10)
file(GENERATE OUTPUT .gitignore CONTENT "*")
{
"version": 6,
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build"
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default"
}
],
"testPresets": [
{
"name": "default",
"configurePreset": "default",
"output": {
"outputOnFailure": true,
"verbosity": "verbose"
},
"execution": {
"noTestsAction": "error",
"scheduleRandom": false,
"stopOnFailure": false,
"timeout": 60,
"jobs": 1
}
}
],
"workflowPresets": [
{
"name": "default",
"steps": [
{
"type": "configure",
"name": "default"
},
{
"type": "build",
"name": "default"
},
{
"type": "test",
"name": "default"
}
]
}
]
}
# Observe for Python flush=False, the printing is buffered till the first flush=True
cmake_minimum_required(VERSION 3.19)
find_package(Python COMPONENTS Interpreter REQUIRED)
execute_process(COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/print_flush.py
RESULT_VARIABLE ret
)
if(ret EQUAL 0)
message(STATUS "OK: print_flush")
else()
message(FATAL_ERROR "print_flush failed: ${ret}")
endif()
// https://en.cppreference.com/w/cpp/io/manip/endl
// https://en.cppreference.com/w/cpp/io/cout
// https://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio
//
// This program is used to show that CTest execution doesn't update the console output until flushed.
// This can be an issue with test programs that exit abnormally.
#include <chrono>
#include <thread>
#include <cstdlib>
#include <iostream>
#include <ostream> // for std::endl
constexpr int milliseconds = 200;
constexpr int N = 6;
int main(){
std::cout << "flush: True" << std::endl;
for (int i = 0; i < N; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
std::cout << (float(i) / N) * 100 << " %" << std::endl;
}
std::cout << "flush: False\n";
std::cout.sync_with_stdio(false);
// https://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio
// on some platforms, stdout flushes on \n by default. This setting disables that.
for (int i = 0; i < N; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
std::cout << (float(i) / N) * 100 << " %\n";
}
return EXIT_SUCCESS;
}
#!/usr/bin/env python3
"""
print() without flush and with flush
https://docs.python.org/3/library/functions.html#print
"""
from time import sleep
N = 6 # arbitrary number of prints
for flush in (True, False):
print("flush:", flush)
for i in range(N):
sleep(0.2)
print(f"{i/N*100:.1f} %", flush=flush)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment