Okay I think this might be a very special case with the SCons script invocation.
The main python script / SCons probably internally creates a new process for each invocation of a user’s extra_script
. And there’s some mechanism to read from that process’s output and display it back in the main processes’s output. But that thing is also buffered or reads line-wise. A simple test like
import sys
Import("env")
print("Normal output")
print("No newline at end but flushed", end="")
sys.stdout.flush()
env.Exit(-1)
as an extra_scripts
script reveals output
Dependency Graph
|-- <ESP8266WiFi> 1.0 (C:\Users\Max\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi)
Building in release mode
Normal output
======================== [FAILED] Took 0.99 seconds ========================
so the second output is not displayed although we flush the output of our process. If one would execute that as a normal python script (with env
stuff removed)
>python test.py
Normal output
No newline at end but flushed
it does output.
@ivankravets do you know about these special cases when an extra_script does print something but without a newline (but still flushes) why it wouldn’t output something in the terminal?
The special usecase here is that e.g. pio run -t specialgdb
would launch the user, in the terminal, in a GDB session, but when using code like
import os
import re
import sys
import time
import subprocess
Import("env")
#print(env.Dump())
gdb_path = ""
# Find the current platform compiler by searching the $PATH
# which will be in a platformio toolchain bin folder
path_regex = re.escape(env['PROJECT_PACKAGES_DIR'])
gcc = "gdb"
if env['PLATFORM'] == 'win32':
path_separator = ';'
path_regex += r'.*\\bin'
gcc += ".exe"
else:
path_separator = ':'
path_regex += r'/.+/bin'
# Search for the compiler
print("PATH: " + str(env['ENV']['PATH'].split(path_separator)))
for pathdir in env['ENV']['PATH'].split(path_separator):
if not re.search(path_regex, pathdir, re.IGNORECASE):
continue
for filepath in os.listdir(pathdir):
if not filepath.endswith(gcc):
continue
# Use entire path to not rely on env PATH
filepath = os.path.sep.join([pathdir, filepath])
print("Compiler found: " + str(filepath))
gdb_path = str(filepath)
def command_gdb(*args, **kwargs):
print("Entrypoint")
# attempt to set output to unbuffered - unsuccessfull though
os.environ["PYTHONUNBUFFERED"] = "1"
print("GDB path = " + gdb_path)
# does not work: input is not echoed, "(gdb)" prompt does not appear
os.system(gdb_path)
#os.execl(gdb_path, "--help")
# workaround.
# for windows: "start" <command> opens .exe directly wihch opens a cmd "GUI" window.
# for linux we probably want to open a new GUI shell or something?
# process output is not displayed inline..
#subprocess.Popen(["start", gdb_path], bufsize=0, shell=True, start_new_session=True, stdout=sys.stdout, stdin=sys.stdin).wait()
env.AddCustomTarget(
name="specialgdb",
dependencies=None,
actions=[
command_gdb
],
title="Launch special GDB",
description="Launch special GDB"
)
the output is
command_gdb(["specialgdb"], [])
Entrypoint
GDB path = C:\Users\Max\.platformio\packages\toolchain-xtensa\bin\xtensa-lx106-elf-gdb.exe
GNU gdb (GDB) 8.2.50.20180723-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-w64-mingw32 --target=xtensa-lx106-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
when the final lines should have been, when just invoking the program
Also output is not echoed which is a mystery to me.
@csetera there’s also a workaround at the bottom of that code that you might want to look at.
One can also do other fancy workarounds. Like e.g., let the Python script write a .bat
file that has the correct invocation line and then wrap it like pio run -t specialgdb && run_gdb.bat
in one command