1010 *******************************************************************************/
1111package org .eclipse .cdt .core .build ;
1212
13- import java .io .BufferedReader ;
1413import java .io .File ;
1514import java .io .FileReader ;
1615import java .io .FileWriter ;
1716import java .io .IOException ;
18- import java .io .InputStream ;
19- import java .io .InputStreamReader ;
20- import java .io .OutputStream ;
21- import java .io .PrintStream ;
2217import java .net .URI ;
2318import java .nio .file .Files ;
2419import java .nio .file .InvalidPathException ;
3328import java .util .Map .Entry ;
3429import java .util .Properties ;
3530import java .util .Set ;
31+ import java .util .stream .Collectors ;
3632
3733import org .eclipse .cdt .core .CCorePlugin ;
3834import org .eclipse .cdt .core .CommandLauncherManager ;
35+ import org .eclipse .cdt .core .ICommandLauncher ;
3936import org .eclipse .cdt .core .IConsoleParser ;
4037import org .eclipse .cdt .core .IConsoleParser2 ;
4138import org .eclipse .cdt .core .IMarkerGenerator ;
6057import org .eclipse .cdt .core .parser .IScannerInfo ;
6158import org .eclipse .cdt .core .parser .IScannerInfoChangeListener ;
6259import org .eclipse .cdt .core .resources .IConsole ;
60+ import org .eclipse .cdt .internal .core .BuildRunnerHelper ;
61+ import org .eclipse .cdt .internal .core .ConsoleOutputSniffer ;
6362import org .eclipse .cdt .internal .core .build .Messages ;
6463import org .eclipse .cdt .internal .core .model .BinaryRunner ;
6564import org .eclipse .cdt .internal .core .model .CModelManager ;
@@ -116,6 +115,8 @@ public abstract class CBuildConfiguration extends PlatformObject implements ICBu
116115 private final Map <IResource , List <IScannerInfoChangeListener >> scannerInfoListeners = new HashMap <>();
117116 private ScannerInfoCache scannerInfoCache ;
118117
118+ private ICommandLauncher launcher ;
119+
119120 protected CBuildConfiguration (IBuildConfiguration config , String name ) throws CoreException {
120121 this .config = config ;
121122 this .name = name ;
@@ -488,7 +489,8 @@ public Process startBuildProcess(List<String> commands, IEnvironmentVariable[] e
488489 .write (String .format (Messages .CBuildConfiguration_CommandNotFound , commands .get (0 )));
489490 return null ;
490491 }
491- commands .set (0 , commandPath .toString ());
492+ IPath cmd = new org .eclipse .core .runtime .Path (commandPath .toString ());
493+ List <String > args = commands .subList (1 , commands .size ());
492494
493495 // check if includes have been removed/refreshed and scanner info refresh is needed
494496 boolean needRefresh = CommandLauncherManager .getInstance ().checkIfIncludesChanged (this );
@@ -497,18 +499,28 @@ public Process startBuildProcess(List<String> commands, IEnvironmentVariable[] e
497499 t .setProperty (NEED_REFRESH , Boolean .valueOf (needRefresh ).toString ());
498500 }
499501
500- ProcessBuilder processBuilder = new ProcessBuilder (commands ).directory (buildDirectory .toFile ());
501- // Override environment variables
502- Map <String , String > environment = processBuilder .environment ();
502+ // Generate environment block before launching process
503+ launcher = CommandLauncherManager .getInstance ().getCommandLauncher (this );
504+ Properties envProps = launcher .getEnvironment ();
505+ HashMap <String , String > environment = envProps .entrySet ().stream ()
506+ .collect (Collectors .toMap (e -> String .valueOf (e .getKey ()), e -> String .valueOf (e .getValue ()),
507+ (prev , next ) -> next , HashMap ::new ));
503508 for (IEnvironmentVariable envVar : envVars ) {
504509 environment .put (envVar .getName (), envVar .getValue ());
505510 }
506511 setBuildEnvironment (environment );
507- process = processBuilder .start ();
512+ launcher .setProject (getProject ());
513+ process = launcher .execute (cmd , args .toArray (new String [0 ]), BuildRunnerHelper .envMapToEnvp (environment ),
514+ buildDirectory , monitor );
508515 }
509516 return process ;
510517 }
511518
519+ /**
520+ * @return The exit code of the build process.
521+ *
522+ * @deprecated use {@link #watchProcess(IConsole, IProgressMonitor)} or {@link #watchProcess(IConsoleParser[], IProgressMonitor)} instead
523+ */
512524 @ Deprecated
513525 protected int watchProcess (Process process , IConsoleParser [] consoleParsers , IConsole console )
514526 throws CoreException {
@@ -520,110 +532,42 @@ protected int watchProcess(Process process, IConsoleParser[] consoleParsers, ICo
520532 }
521533
522534 /**
535+ * @return The exit code of the build process.
523536 * @since 6.4
537+ *
538+ * @deprecated use {@link #watchProcess(IConsole, IProgressMonitor)} instead and pass in a monitor
524539 */
540+ @ Deprecated
525541 protected int watchProcess (Process process , IConsole console ) throws CoreException {
526- Thread t1 = new ReaderThread (process .getInputStream (), console .getOutputStream ());
527- t1 .start ();
528- Thread t2 = new ReaderThread (process .getErrorStream (), console .getErrorStream ());
529- t2 .start ();
530- try {
531- int rc = process .waitFor ();
532- // Allow reader threads the chance to process all output to console
533- while (t1 .isAlive ()) {
534- Thread .sleep (100 );
535- }
536- while (t2 .isAlive ()) {
537- Thread .sleep (100 );
538- }
539- return rc ;
540- } catch (InterruptedException e ) {
541- CCorePlugin .log (e );
542- return -1 ;
543- }
542+ return watchProcess (console , new NullProgressMonitor ());
544543 }
545544
546545 /**
546+ * @return The exit code of the build process.
547+ * @since 7.5
548+ */
549+ protected int watchProcess (IConsole console , IProgressMonitor monitor ) throws CoreException {
550+ return launcher .waitAndRead (console .getInfoStream (), console .getErrorStream (), monitor );
551+ }
552+
553+ /**
554+ * @return The exit code of the build process.
547555 * @since 6.4
556+ *
557+ * @deprecated use {@link #watchProcess(IConsoleParser[], IProgressMonitor)} instead and pass in a monitor
548558 */
559+ @ Deprecated
549560 protected int watchProcess (Process process , IConsoleParser [] consoleParsers ) throws CoreException {
550- Thread t1 = new ReaderThread (this , process .getInputStream (), consoleParsers );
551- t1 .start ();
552- Thread t2 = new ReaderThread (this , process .getErrorStream (), consoleParsers );
553- t2 .start ();
554- try {
555- int rc = process .waitFor ();
556- // Allow reader threads the chance to process all output to console
557- while (t1 .isAlive ()) {
558- Thread .sleep (100 );
559- }
560- while (t2 .isAlive ()) {
561- Thread .sleep (100 );
562- }
563- return rc ;
564- } catch (InterruptedException e ) {
565- CCorePlugin .log (e );
566- return -1 ;
567- }
561+ return watchProcess (consoleParsers , new NullProgressMonitor ());
568562 }
569563
570- private static class ReaderThread extends Thread {
571- CBuildConfiguration config ;
572- private final BufferedReader in ;
573- private final IConsoleParser [] consoleParsers ;
574- private final PrintStream out ;
575-
576- public ReaderThread (CBuildConfiguration config , InputStream in , IConsoleParser [] consoleParsers ) {
577- this .config = config ;
578- this .in = new BufferedReader (new InputStreamReader (in ));
579- this .out = null ;
580- this .consoleParsers = consoleParsers ;
581- }
582-
583- public ReaderThread (InputStream in , OutputStream out ) {
584- this .in = new BufferedReader (new InputStreamReader (in ));
585- this .out = new PrintStream (out );
586- this .consoleParsers = null ;
587- this .config = null ;
588- }
589-
590- @ Override
591- public void run () {
592- List <Job > jobList = new ArrayList <>();
593- try {
594- for (String line = in .readLine (); line != null ; line = in .readLine ()) {
595- if (consoleParsers != null ) {
596- for (IConsoleParser consoleParser : consoleParsers ) {
597- // Synchronize to avoid interleaving of lines
598- synchronized (consoleParser ) {
599- // if we have an IConsoleParser2, use the processLine method that
600- // takes a job list (Container Build support)
601- if (consoleParser instanceof IConsoleParser2 ) {
602- ((IConsoleParser2 ) consoleParser ).processLine (line , jobList );
603- } else {
604- consoleParser .processLine (line );
605- }
606- }
607- }
608- }
609- if (out != null ) {
610- out .println (line );
611- }
612- }
613- for (Job j : jobList ) {
614- try {
615- j .join ();
616- } catch (InterruptedException e ) {
617- // ignore
618- }
619- }
620- if (config != null ) {
621- config .shutdown ();
622- }
623- } catch (IOException e ) {
624- CCorePlugin .log (e );
625- }
626- }
564+ /**
565+ * @return The exit code of the build process.
566+ * @since 7.5
567+ */
568+ protected int watchProcess (IConsoleParser [] consoleParsers , IProgressMonitor monitor ) throws CoreException {
569+ ConsoleOutputSniffer sniffer = new ConsoleOutputSniffer (consoleParsers );
570+ return launcher .waitAndRead (sniffer .getOutputStream (), sniffer .getErrorStream (), monitor );
627571 }
628572
629573 private File getScannerInfoCacheFile () {
0 commit comments