[Support] On Windows, generate PDF files for graphs and open with associated viewer
authorMichael Kruse <llvm@meinersbur.de>
Tue, 18 Aug 2015 12:17:37 +0000 (12:17 +0000)
committerMichael Kruse <llvm@meinersbur.de>
Tue, 18 Aug 2015 12:17:37 +0000 (12:17 +0000)
Summary: Windows system rarely have good PostScript viewers installed, but PDF viewers are common. So for viewing graphs, generate PDF files and open with the associated PDF viewer using cmd.exe's start command.

Reviewers: Bigcheese, aaron.ballman

Subscribers: aaron.ballman, JakeVanAdrighem, dwiberg, llvm-commits

Differential Revision: http://reviews.llvm.org/D11877

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245290 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/GraphWriter.cpp

index 0bbfde232a104a4e92a8c5caa7a1649158d5a735..cbf534933370337df2385708ca2e9cbeb10f0f9e 100644 (file)
@@ -189,61 +189,87 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
   }
 
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
   }
 
-  enum PSViewerKind { PSV_None, PSV_OSXOpen, PSV_XDGOpen, PSV_Ghostview };
-  PSViewerKind PSViewer = PSV_None;
+  enum ViewerKind {
+    VK_None,
+    VK_OSXOpen,
+    VK_XDGOpen,
+    VK_Ghostview,
+    VK_CmdStart
+  };
+  ViewerKind Viewer = VK_None;
 #ifdef __APPLE__
 #ifdef __APPLE__
-  if (!PSViewer && S.TryFindProgram("open", ViewerPath))
-    PSViewer = PSV_OSXOpen;
+  if (!Viewer && S.TryFindProgram("open", ViewerPath))
+    Viewer = VK_OSXOpen;
+#endif
+  if (!Viewer && S.TryFindProgram("gv", ViewerPath))
+    Viewer = VK_Ghostview;
+  if (!Viewer && S.TryFindProgram("xdg-open", ViewerPath))
+    Viewer = VK_XDGOpen;
+#ifdef LLVM_ON_WIN32
+  if (!Viewer && S.TryFindProgram("cmd", ViewerPath)) {
+    Viewer = VK_CmdStart;
+  }
 #endif
 #endif
-  if (!PSViewer && S.TryFindProgram("gv", ViewerPath))
-    PSViewer = PSV_Ghostview;
-  if (!PSViewer && S.TryFindProgram("xdg-open", ViewerPath))
-    PSViewer = PSV_XDGOpen;
 
 
-  // PostScript graph generator + PostScript viewer
+  // PostScript or PDF graph generator + PostScript/PDF viewer
   std::string GeneratorPath;
   std::string GeneratorPath;
-  if (PSViewer &&
+  if (Viewer &&
       (S.TryFindProgram(getProgramName(program), GeneratorPath) ||
        S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) {
       (S.TryFindProgram(getProgramName(program), GeneratorPath) ||
        S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) {
-    std::string PSFilename = Filename + ".ps";
+    std::string OutputFilename =
+        Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps");
 
     std::vector<const char *> args;
     args.push_back(GeneratorPath.c_str());
 
     std::vector<const char *> args;
     args.push_back(GeneratorPath.c_str());
-    args.push_back("-Tps");
+    if (Viewer == VK_CmdStart)
+      args.push_back("-Tpdf");
+    else
+      args.push_back("-Tps");
     args.push_back("-Nfontname=Courier");
     args.push_back("-Gsize=7.5,10");
     args.push_back(Filename.c_str());
     args.push_back("-o");
     args.push_back("-Nfontname=Courier");
     args.push_back("-Gsize=7.5,10");
     args.push_back(Filename.c_str());
     args.push_back("-o");
-    args.push_back(PSFilename.c_str());
+    args.push_back(OutputFilename.c_str());
     args.push_back(nullptr);
 
     errs() << "Running '" << GeneratorPath << "' program... ";
 
     args.push_back(nullptr);
 
     errs() << "Running '" << GeneratorPath << "' program... ";
 
-    if (ExecGraphViewer(GeneratorPath, args, Filename, true, ErrMsg))
+    if (ExecGraphViewer(GeneratorPath, args, Filename, wait, ErrMsg))
       return true;
 
       return true;
 
+    // The lifetime of StartArg must include the call of ExecGraphViewer
+    // because the args are passed as vector of char*.
+    std::string StartArg;
+
     args.clear();
     args.push_back(ViewerPath.c_str());
     args.clear();
     args.push_back(ViewerPath.c_str());
-    switch (PSViewer) {
-    case PSV_OSXOpen:
+    switch (Viewer) {
+    case VK_OSXOpen:
       args.push_back("-W");
       args.push_back("-W");
-      args.push_back(PSFilename.c_str());
+      args.push_back(OutputFilename.c_str());
       break;
       break;
-    case PSV_XDGOpen:
+    case VK_XDGOpen:
       wait = false;
       wait = false;
-      args.push_back(PSFilename.c_str());
+      args.push_back(OutputFilename.c_str());
       break;
       break;
-    case PSV_Ghostview:
+    case VK_Ghostview:
       args.push_back("--spartan");
       args.push_back("--spartan");
-      args.push_back(PSFilename.c_str());
+      args.push_back(OutputFilename.c_str());
+      break;
+    case VK_CmdStart:
+      args.push_back("/S");
+      args.push_back("/C");
+      StartArg =
+          (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str();
+      args.push_back(StartArg.c_str());
       break;
       break;
-    case PSV_None:
+    case VK_None:
       llvm_unreachable("Invalid viewer");
     }
     args.push_back(nullptr);
 
     ErrMsg.clear();
       llvm_unreachable("Invalid viewer");
     }
     args.push_back(nullptr);
 
     ErrMsg.clear();
-    return ExecGraphViewer(ViewerPath, args, PSFilename, wait, ErrMsg);
+    return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg);
   }
 
   // dotty
   }
 
   // dotty