devshell.bbclass 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. inherit terminal
  2. DEVSHELL = "${SHELL}"
  3. python do_devshell () {
  4. if d.getVarFlag("do_devshell", "manualfakeroot"):
  5. d.prependVar("DEVSHELL", "pseudo ")
  6. fakeenv = d.getVar("FAKEROOTENV").split()
  7. for f in fakeenv:
  8. k = f.split("=")
  9. d.setVar(k[0], k[1])
  10. d.appendVar("OE_TERMINAL_EXPORTS", " " + k[0])
  11. d.delVarFlag("do_devshell", "fakeroot")
  12. oe_terminal(d.getVar('DEVSHELL'), 'OpenEmbedded Developer Shell', d)
  13. }
  14. addtask devshell after do_patch do_prepare_recipe_sysroot
  15. # The directory that the terminal starts in
  16. DEVSHELL_STARTDIR ?= "${S}"
  17. do_devshell[dirs] = "${DEVSHELL_STARTDIR}"
  18. do_devshell[nostamp] = "1"
  19. # devshell and fakeroot/pseudo need careful handling since only the final
  20. # command should run under fakeroot emulation, any X connection should
  21. # be done as the normal user. We therfore carefully construct the envionment
  22. # manually
  23. python () {
  24. if d.getVarFlag("do_devshell", "fakeroot"):
  25. # We need to signal our code that we want fakeroot however we
  26. # can't manipulate the environment and variables here yet (see YOCTO #4795)
  27. d.setVarFlag("do_devshell", "manualfakeroot", "1")
  28. d.delVarFlag("do_devshell", "fakeroot")
  29. }
  30. def devpyshell(d):
  31. import code
  32. import select
  33. import signal
  34. import termios
  35. m, s = os.openpty()
  36. sname = os.ttyname(s)
  37. def noechoicanon(fd):
  38. old = termios.tcgetattr(fd)
  39. old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
  40. # &~ termios.ISIG
  41. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  42. # No echo or buffering over the pty
  43. noechoicanon(s)
  44. pid = os.fork()
  45. if pid:
  46. os.close(m)
  47. oe_terminal("oepydevshell-internal.py %s %d" % (sname, pid), 'OpenEmbedded Developer PyShell', d)
  48. os._exit(0)
  49. else:
  50. os.close(s)
  51. os.dup2(m, sys.stdin.fileno())
  52. os.dup2(m, sys.stdout.fileno())
  53. os.dup2(m, sys.stderr.fileno())
  54. bb.utils.nonblockingfd(sys.stdout)
  55. bb.utils.nonblockingfd(sys.stderr)
  56. bb.utils.nonblockingfd(sys.stdin)
  57. _context = {
  58. "os": os,
  59. "bb": bb,
  60. "time": time,
  61. "d": d,
  62. }
  63. ps1 = "pydevshell> "
  64. ps2 = "... "
  65. buf = []
  66. more = False
  67. i = code.InteractiveInterpreter(locals=_context)
  68. print("OE PyShell (PN = %s)\n" % d.getVar("PN"))
  69. def prompt(more):
  70. if more:
  71. prompt = ps2
  72. else:
  73. prompt = ps1
  74. sys.stdout.write(prompt)
  75. sys.stdout.flush()
  76. # Restore Ctrl+C since bitbake masks this
  77. def signal_handler(signal, frame):
  78. raise KeyboardInterrupt
  79. signal.signal(signal.SIGINT, signal_handler)
  80. child = None
  81. prompt(more)
  82. while True:
  83. try:
  84. try:
  85. (r, _, _) = select.select([sys.stdin], [], [], 1)
  86. if not r:
  87. continue
  88. line = sys.stdin.readline().strip()
  89. if not line:
  90. prompt(more)
  91. continue
  92. except EOFError as e:
  93. sys.stdout.write("\n")
  94. sys.stdout.flush()
  95. except (OSError, IOError) as e:
  96. if e.errno == 11:
  97. continue
  98. if e.errno == 5:
  99. return
  100. raise
  101. else:
  102. if not child:
  103. child = int(line)
  104. continue
  105. buf.append(line)
  106. source = "\n".join(buf)
  107. more = i.runsource(source, "<pyshell>")
  108. if not more:
  109. buf = []
  110. prompt(more)
  111. except KeyboardInterrupt:
  112. i.write("\nKeyboardInterrupt\n")
  113. buf = []
  114. more = False
  115. prompt(more)
  116. except SystemExit:
  117. # Easiest way to ensure everything exits
  118. os.kill(child, signal.SIGTERM)
  119. break
  120. python do_devpyshell() {
  121. import signal
  122. try:
  123. devpyshell(d)
  124. except SystemExit:
  125. # Stop the SIGTERM above causing an error exit code
  126. return
  127. finally:
  128. return
  129. }
  130. addtask devpyshell after do_patch
  131. do_devpyshell[nostamp] = "1"