llvm.org GIT mirror llvm / 04de60e
GraphWriter: detect graph viewer programs at runtime Replace the crufty build-time configure checks for program paths with equivalent runtime logic. This lets users install graphing tools as needed without having to reconfigure and rebuild LLVM, while eliminating a long chain of inappropriate compile dependencies that included GUI programs and the windowing system. Additional features: * Support the OS X 'open' command to view graphs generated by any of the Graphviz utilities. This is an alternative to the Graphviz OS X UI which is no longer available on Mountain Lion. * Produce informative log output upon failure to indicate which programs can be installed to view graphs. Ping me if this doesn't work for your particular environment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210001 91177308-0d34-0410-b5e6-96231b3b80d8 Alp Toker 5 years ago
9 changed file(s) with 150 addition(s) and 387 deletion(s). Raw diff Collapse all Expand all
12811281 AC_PATH_PROG(BINPWD,[pwd], [pwd])
12821282
12831283 dnl Looking for misc. graph plotting software
1284 AC_PATH_PROG(GRAPHVIZ, [Graphviz], [echo Graphviz])
1285 if test "$GRAPHVIZ" != "echo Graphviz" ; then
1286 AC_DEFINE([HAVE_GRAPHVIZ],[1],[Define if the Graphviz program is available])
1287 dnl If we're targeting for mingw we should emit windows paths, not msys
1288 if test "$llvm_cv_os_type" = "MingW" ; then
1289 GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1290 fi
1291 AC_DEFINE_UNQUOTED([LLVM_PATH_GRAPHVIZ],"$GRAPHVIZ${EXEEXT}",
1292 [Define to path to Graphviz program if found or 'echo Graphviz' otherwise])
1293 fi
12941284 AC_PATH_PROG(DOT, [dot], [echo dot])
12951285 if test "$DOT" != "echo dot" ; then
12961286 AC_DEFINE([HAVE_DOT],[1],[Define if the dot program is available])
13001290 fi
13011291 AC_DEFINE_UNQUOTED([LLVM_PATH_DOT],"$DOT${EXEEXT}",
13021292 [Define to path to dot program if found or 'echo dot' otherwise])
1303 fi
1304 AC_PATH_PROG(FDP, [fdp], [echo fdp])
1305 if test "$FDP" != "echo fdp" ; then
1306 AC_DEFINE([HAVE_FDP],[1],[Define if the neat program is available])
1307 dnl If we're targeting for mingw we should emit windows paths, not msys
1308 if test "$llvm_cv_os_type" = "MingW" ; then
1309 FDP=`echo $FDP | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1310 fi
1311 AC_DEFINE_UNQUOTED([LLVM_PATH_FDP],"$FDP${EXEEXT}",
1312 [Define to path to fdp program if found or 'echo fdp' otherwise])
1313 fi
1314 AC_PATH_PROG(NEATO, [neato], [echo neato])
1315 if test "$NEATO" != "echo neato" ; then
1316 AC_DEFINE([HAVE_NEATO],[1],[Define if the neat program is available])
1317 dnl If we're targeting for mingw we should emit windows paths, not msys
1318 if test "$llvm_cv_os_type" = "MingW" ; then
1319 NEATO=`echo $NEATO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1320 fi
1321 AC_DEFINE_UNQUOTED([LLVM_PATH_NEATO],"$NEATO${EXEEXT}",
1322 [Define to path to neato program if found or 'echo neato' otherwise])
1323 fi
1324 AC_PATH_PROG(TWOPI, [twopi], [echo twopi])
1325 if test "$TWOPI" != "echo twopi" ; then
1326 AC_DEFINE([HAVE_TWOPI],[1],[Define if the neat program is available])
1327 dnl If we're targeting for mingw we should emit windows paths, not msys
1328 if test "$llvm_cv_os_type" = "MingW" ; then
1329 TWOPI=`echo $TWOPI | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1330 fi
1331 AC_DEFINE_UNQUOTED([LLVM_PATH_TWOPI],"$TWOPI${EXEEXT}",
1332 [Define to path to twopi program if found or 'echo twopi' otherwise])
1333 fi
1334 AC_PATH_PROG(CIRCO, [circo], [echo circo])
1335 if test "$CIRCO" != "echo circo" ; then
1336 AC_DEFINE([HAVE_CIRCO],[1],[Define if the neat program is available])
1337 dnl If we're targeting for mingw we should emit windows paths, not msys
1338 if test "$llvm_cv_os_type" = "MingW" ; then
1339 CIRCO=`echo $CIRCO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1340 fi
1341 AC_DEFINE_UNQUOTED([LLVM_PATH_CIRCO],"$CIRCO${EXEEXT}",
1342 [Define to path to circo program if found or 'echo circo' otherwise])
1343 fi
1344 AC_PATH_PROGS(GV, [gv gsview32], [echo gv])
1345 if test "$GV" != "echo gv" ; then
1346 AC_DEFINE([HAVE_GV],[1],[Define if the gv program is available])
1347 dnl If we're targeting for mingw we should emit windows paths, not msys
1348 if test "$llvm_cv_os_type" = "MingW" ; then
1349 GV=`echo $GV | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1350 fi
1351 AC_DEFINE_UNQUOTED([LLVM_PATH_GV],"$GV${EXEEXT}",
1352 [Define to path to gv program if found or 'echo gv' otherwise])
1353 fi
1354 AC_PATH_PROG(DOTTY, [dotty], [echo dotty])
1355 if test "$DOTTY" != "echo dotty" ; then
1356 AC_DEFINE([HAVE_DOTTY],[1],[Define if the dotty program is available])
1357 dnl If we're targeting for mingw we should emit windows paths, not msys
1358 if test "$llvm_cv_os_type" = "MingW" ; then
1359 DOTTY=`echo $DOTTY | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1360 fi
1361 AC_DEFINE_UNQUOTED([LLVM_PATH_DOTTY],"$DOTTY${EXEEXT}",
1362 [Define to path to dotty program if found or 'echo dotty' otherwise])
1363 fi
1364 AC_PATH_PROGS(XDOT, [xdot xdot.py], [echo xdot])
1365 if test "$XDOT" != "echo xdot" ; then
1366 AC_DEFINE([HAVE_XDOT],[1],[Define if the xdot program is available])
1367 dnl If we're targeting for mingw we should emit windows paths, not msys
1368 if test "$llvm_cv_os_type" = "MingW" ; then
1369 XDOT=`echo $XDOT | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' `
1370 fi
1371 AC_DEFINE_UNQUOTED([LLVM_PATH_XDOT],"$XDOT${EXEEXT}",
1372 [Define to path to xdot program if found or 'echo xdot' otherwise])
13731293 fi
13741294
13751295 dnl Find the install program
251251 endif(LLVM_PATH_${NAME})
252252 endfunction()
253253
254 llvm_find_program(gv)
255 llvm_find_program(circo)
256 llvm_find_program(twopi)
257 llvm_find_program(neato)
258 llvm_find_program(fdp)
259 llvm_find_program(dot)
260 llvm_find_program(dotty)
261 llvm_find_program(xdot xdot.py)
262 llvm_find_program(Graphviz)
254 if (LLVM_ENABLE_DOXYGEN)
255 llvm_find_program(dot)
256 endif ()
263257
264258 if( LLVM_ENABLE_FFI )
265259 find_path(FFI_INCLUDE_PATH ffi.h PATHS ${FFI_INCLUDE_DIR})
544544 DAG.viewGraph()`` to pop up a window. Alternatively, you can sprinkle calls to
545545 these functions in your code in places you want to debug.
546546
547 Getting this to work requires a small amount of configuration. On Unix systems
547 Getting this to work requires a small amount of setup. On Unix systems
548548 with X11, install the `graphviz `_ toolkit, and make
549549 sure 'dot' and 'gv' are in your path. If you are running on Mac OS X, download
550550 and install the Mac OS X `Graphviz program
551551 `_ and add
552552 ``/Applications/Graphviz.app/Contents/MacOS/`` (or wherever you install it) to
553 your path. Once in your system and path are set up, rerun the LLVM configure
554 script and rebuild LLVM to enable this functionality.
553 your path. The programs need not be present when configuring, building or
554 running LLVM and can simply be installed when needed during an active debug
555 session.
555556
556557 ``SelectionDAG`` has been extended to make it easier to locate *interesting*
557558 nodes in large complex graphs. From gdb, if you ``call DAG.setGraphColor(node,
4343
4444 /* Define to 1 if you have the `ceilf' function. */
4545 #cmakedefine HAVE_CEILF ${HAVE_CEILF}
46
47 /* Define if the neat program is available */
48 #cmakedefine HAVE_CIRCO ${HAVE_CIRCO}
4946
5047 /* Define to 1 if you have the `closedir' function. */
5148 #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR}
7976 /* Define if dlopen() is available on this platform. */
8077 #cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
8178
82 /* Define if the dot program is available */
83 #cmakedefine HAVE_DOT ${HAVE_DOT}
84
85 /* Define if the dotty program is available */
86 #cmakedefine HAVE_DOTTY ${HAVE_DOTTY}
87
8879 /* Define if you have the _dyld_func_lookup function. */
8980 #undef HAVE_DYLD
9081
9788 /* Define to 1 if you have the header file. */
9889 #cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
9990
100 /* Define if the neat program is available */
101 #cmakedefine HAVE_FDP ${HAVE_FDP}
102
10391 /* Define to 1 if you have the header file. */
10492 #cmakedefine HAVE_FENV_H ${HAVE_FENV_H}
10593
159147
160148 /* Define to 1 if you have the `gettimeofday' function. */
161149 #cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY}
162
163 /* Define if the Graphviz program is available */
164 #cmakedefine HAVE_GRAPHVIZ ${HAVE_GRAPHVIZ}
165
166 /* Define if the gv program is available */
167 #cmakedefine HAVE_GV ${HAVE_GV}
168150
169151 /* Define to 1 if the system has the type `int64_t'. */
170152 #cmakedefine HAVE_INT64_T ${HAVE_INT64_T}
270252 /* Define to 1 if you have the `nearbyintf' function. */
271253 #cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF}
272254
273 /* Define if the neat program is available */
274 #cmakedefine HAVE_NEATO ${HAVE_NEATO}
275
276255 /* Define to 1 if you have the `opendir' function. */
277256 #cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR}
278257
416395 /* Define to 1 if you have the header file. */
417396 #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
418397
419 /* Define if the neat program is available */
420 #cmakedefine HAVE_TWOPI ${HAVE_TWOPI}
421
422398 /* Define to 1 if the system has the type `uint64_t'. */
423399 #cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T}
424400
437413 /* Define to 1 if you have the `writev' function. */
438414 #cmakedefine HAVE_WRITEV ${HAVE_WRITEV}
439415
440 /* Define if the xdot.py program is available */
441 #cmakedefine HAVE_XDOT ${HAVE_XDOT}
442
443416 /* Define to 1 if you have the header file. */
444417 #cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H}
445418
565538
566539 /* Define if this is Win32ish platform */
567540 #cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
568
569 /* Define to path to circo program if found or 'echo circo' otherwise */
570 #cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}"
571
572 /* Define to path to dot program if found or 'echo dot' otherwise */
573 #cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}"
574
575 /* Define to path to dotty program if found or 'echo dotty' otherwise */
576 #cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}"
577
578 /* Define to path to fdp program if found or 'echo fdp' otherwise */
579 #cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}"
580
581 /* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
582 #cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}"
583
584 /* Define to path to gv program if found or 'echo gv' otherwise */
585 #cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}"
586
587 /* Define to path to neato program if found or 'echo neato' otherwise */
588 #cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}"
589
590 /* Define to path to twopi program if found or 'echo twopi' otherwise */
591 #cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}"
592
593 /* Define to path to xdot.py program if found or 'echo xdot' otherwise */
594 #cmakedefine LLVM_PATH_XDOT "${LLVM_PATH_XDOT}"
595541
596542 /* Installation prefix directory */
597543 #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}"
3737
3838 /* Define to 1 if you have the `ceilf' function. */
3939 #undef HAVE_CEILF
40
41 /* Define if the neat program is available */
42 #undef HAVE_CIRCO
4340
4441 /* Define to 1 if you have the header file. */
4542 #undef HAVE_CRASHREPORTERCLIENT_H
7673 /* Define if dlopen() is available on this platform. */
7774 #undef HAVE_DLOPEN
7875
79 /* Define if the dot program is available */
80 #undef HAVE_DOT
81
82 /* Define if the dotty program is available */
83 #undef HAVE_DOTTY
84
8576 /* Define to 1 if you have the header file. */
8677 #undef HAVE_ERRNO_H
8778
9788 /* Define to 1 if you have the header file. */
9889 #undef HAVE_FCNTL_H
9990
100 /* Define if the neat program is available */
101 #undef HAVE_FDP
102
10391 /* Define to 1 if you have the header file. */
10492 #undef HAVE_FENV_H
10593
141129
142130 /* Define to 1 if you have the `gettimeofday' function. */
143131 #undef HAVE_GETTIMEOFDAY
144
145 /* Define if the Graphviz program is available */
146 #undef HAVE_GRAPHVIZ
147
148 /* Define if the gv program is available */
149 #undef HAVE_GV
150132
151133 /* Define to 1 if the system has the type `int64_t'. */
152134 #undef HAVE_INT64_T
258240 /* Define to 1 if you have the `nearbyintf' function. */
259241 #undef HAVE_NEARBYINTF
260242
261 /* Define if the neat program is available */
262 #undef HAVE_NEATO
263
264243 /* Define to 1 if you have the `posix_spawn' function. */
265244 #undef HAVE_POSIX_SPAWN
266245
401380 /* Define to 1 if you have the header file. */
402381 #undef HAVE_TERMIOS_H
403382
404 /* Define if the neat program is available */
405 #undef HAVE_TWOPI
406
407383 /* Define to 1 if the system has the type `uint64_t'. */
408384 #undef HAVE_UINT64_T
409385
422398 /* Define to 1 if you have the `writev' function. */
423399 #undef HAVE_WRITEV
424400
425 /* Define if the xdot program is available */
426 #undef HAVE_XDOT
427
428401 /* Define to 1 if you have the header file. */
429402 #undef HAVE_ZLIB_H
430403
547520
548521 /* Define if this is Win32ish platform */
549522 #undef LLVM_ON_WIN32
550
551 /* Define to path to circo program if found or 'echo circo' otherwise */
552 #undef LLVM_PATH_CIRCO
553
554 /* Define to path to dot program if found or 'echo dot' otherwise */
555 #undef LLVM_PATH_DOT
556
557 /* Define to path to dotty program if found or 'echo dotty' otherwise */
558 #undef LLVM_PATH_DOTTY
559
560 /* Define to path to fdp program if found or 'echo fdp' otherwise */
561 #undef LLVM_PATH_FDP
562
563 /* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
564 #undef LLVM_PATH_GRAPHVIZ
565
566 /* Define to path to gv program if found or 'echo gv' otherwise */
567 #undef LLVM_PATH_GV
568
569 /* Define to path to neato program if found or 'echo neato' otherwise */
570 #undef LLVM_PATH_NEATO
571
572 /* Define to path to twopi program if found or 'echo twopi' otherwise */
573 #undef LLVM_PATH_TWOPI
574
575 /* Define to path to xdot program if found or 'echo xdot' otherwise */
576 #undef LLVM_PATH_XDOT
577523
578524 /* Installation prefix directory */
579525 #undef LLVM_PREFIX
7878 /* Define if this is Win32ish platform */
7979 #cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
8080
81 /* Define to path to circo program if found or 'echo circo' otherwise */
82 #cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}"
83
84 /* Define to path to dot program if found or 'echo dot' otherwise */
85 #cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}"
86
87 /* Define to path to dotty program if found or 'echo dotty' otherwise */
88 #cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}"
89
90 /* Define to path to fdp program if found or 'echo fdp' otherwise */
91 #cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}"
92
93 /* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
94 #cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}"
95
96 /* Define to path to gv program if found or 'echo gv' otherwise */
97 #cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}"
98
99 /* Define to path to neato program if found or 'echo neato' otherwise */
100 #cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}"
101
102 /* Define to path to twopi program if found or 'echo twopi' otherwise */
103 #cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}"
104
105 /* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */
106 #cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}"
107
10881 /* Installation prefix directory */
10982 #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}"
11083
7878 /* Define if this is Win32ish platform */
7979 #undef LLVM_ON_WIN32
8080
81 /* Define to path to circo program if found or 'echo circo' otherwise */
82 #undef LLVM_PATH_CIRCO
83
84 /* Define to path to dot program if found or 'echo dot' otherwise */
85 #undef LLVM_PATH_DOT
86
87 /* Define to path to dotty program if found or 'echo dotty' otherwise */
88 #undef LLVM_PATH_DOTTY
89
90 /* Define to path to fdp program if found or 'echo fdp' otherwise */
91 #undef LLVM_PATH_FDP
92
93 /* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */
94 #undef LLVM_PATH_GRAPHVIZ
95
96 /* Define to path to gv program if found or 'echo gv' otherwise */
97 #undef LLVM_PATH_GV
98
99 /* Define to path to neato program if found or 'echo neato' otherwise */
100 #undef LLVM_PATH_NEATO
101
102 /* Define to path to twopi program if found or 'echo twopi' otherwise */
103 #undef LLVM_PATH_TWOPI
104
105 /* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */
106 #undef LLVM_PATH_XDOT_PY
107
10881 /* Installation prefix directory */
10982 #undef LLVM_PREFIX
11083
4949 };
5050 }
5151
52 void DisplayGraph(StringRef Filename, bool wait = true,
52 bool DisplayGraph(StringRef Filename, bool wait = true,
5353 GraphProgram::Name program = GraphProgram::DOT);
5454
5555 template
7777 return Filename.str();
7878 }
7979
80 // Execute the graph viewer. Return true if successful.
81 static bool LLVM_ATTRIBUTE_UNUSED
82 ExecGraphViewer(StringRef ExecPath, std::vector &args,
83 StringRef Filename, bool wait, std::string &ErrMsg) {
80 // Execute the graph viewer. Return true if there were errors.
81 static bool ExecGraphViewer(StringRef ExecPath, std::vector &args,
82 StringRef Filename, bool wait,
83 std::string &ErrMsg) {
84 assert(args.back() == nullptr);
8485 if (wait) {
85 if (sys::ExecuteAndWait(ExecPath, &args[0],nullptr,nullptr,0,0,&ErrMsg)) {
86 if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, nullptr, 0, 0,
87 &ErrMsg)) {
8688 errs() << "Error: " << ErrMsg << "\n";
87 return false;
89 return true;
8890 }
8991 sys::fs::remove(Filename);
9092 errs() << " done. \n";
91 }
92 else {
93 sys::ExecuteNoWait(ExecPath, &args[0],nullptr,nullptr,0,&ErrMsg);
93 } else {
94 sys::ExecuteNoWait(ExecPath, args.data(), nullptr, nullptr, 0, &ErrMsg);
9495 errs() << "Remember to erase graph file: " << Filename.str() << "\n";
9596 }
96 return true;
97 }
98
99 void llvm::DisplayGraph(StringRef FilenameRef, bool wait,
97 return false;
98 }
99
100 struct GraphSession {
101 std::string LogBuffer;
102 bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
103 raw_string_ostream Log(LogBuffer);
104 SmallVector parts;
105 Names.split(parts, "|");
106 for (auto Name : parts) {
107 ProgramPath = sys::FindProgramByName(Name);
108 if (!ProgramPath.empty())
109 return true;
110 Log << " Tried '" << Name << "'\n";
111 }
112 return false;
113 }
114 };
115
116 static const char *getProgramName(GraphProgram::Name program) {
117 switch (program) {
118 case GraphProgram::DOT:
119 return "dot";
120 case GraphProgram::FDP:
121 return "fdp";
122 case GraphProgram::NEATO:
123 return "neato";
124 case GraphProgram::TWOPI:
125 return "twopi";
126 case GraphProgram::CIRCO:
127 return "circo";
128 }
129 }
130
131 bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
100132 GraphProgram::Name program) {
101133 std::string Filename = FilenameRef;
102134 wait &= !ViewBackground;
103135 std::string ErrMsg;
104 #if HAVE_GRAPHVIZ
105 std::string Graphviz(LLVM_PATH_GRAPHVIZ);
106
107 std::vector args;
108 args.push_back(Graphviz.c_str());
109 args.push_back(Filename.c_str());
110 args.push_back(nullptr);
111
112 errs() << "Running 'Graphviz' program... ";
113 if (!ExecGraphViewer(Graphviz, args, Filename, wait, ErrMsg))
114 return;
115
116 #elif HAVE_XDOT
117 std::vector args;
118 args.push_back(LLVM_PATH_XDOT);
119 args.push_back(Filename.c_str());
120
121 switch (program) {
122 case GraphProgram::DOT: args.push_back("-f"); args.push_back("dot"); break;
123 case GraphProgram::FDP: args.push_back("-f"); args.push_back("fdp"); break;
124 case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break;
125 case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break;
126 case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break;
127 }
128
129 args.push_back(0);
130
131 errs() << "Running 'xdot.py' program... ";
132 if (!ExecGraphViewer(LLVM_PATH_XDOT, args, Filename, wait, ErrMsg))
133 return;
134
135 #elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \
136 HAVE_TWOPI || HAVE_CIRCO))
137 std::string PSFilename = Filename + ".ps";
138 std::string prog;
139
140 // Set default grapher
141 #if HAVE_CIRCO
142 prog = LLVM_PATH_CIRCO;
136 std::string ViewerPath;
137 GraphSession S;
138
139 // Graphviz
140 if (S.TryFindProgram("Graphviz", ViewerPath)) {
141 std::vector args;
142 args.push_back(ViewerPath.c_str());
143 args.push_back(Filename.c_str());
144 args.push_back(nullptr);
145
146 errs() << "Running 'Graphviz' program... ";
147 return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
148 }
149
150 // xdot
151 if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
152 std::vector args;
153 args.push_back(ViewerPath.c_str());
154 args.push_back(Filename.c_str());
155
156 args.push_back("-f");
157 args.push_back(getProgramName(program));
158
159 args.push_back(nullptr);
160
161 errs() << "Running 'xdot.py' program... ";
162 return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
163 }
164
165 enum PSViewerKind { PSV_None, PSV_OSXOpen, PSV_Ghostview };
166 PSViewerKind PSViewer = PSV_None;
167 #ifdef __APPLE__
168 if (S.TryFindProgram("open", ViewerPath))
169 PSViewer = PSV_OSXOpen;
143170 #endif
144 #if HAVE_TWOPI
145 prog = LLVM_PATH_TWOPI;
171 if (!PSViewer && S.TryFindProgram("gv", ViewerPath))
172 PSViewer = PSV_Ghostview;
173
174 // PostScript graph generator + PostScript viewer
175 std::string GeneratorPath;
176 if (PSViewer &&
177 (S.TryFindProgram(getProgramName(program), GeneratorPath) ||
178 S.TryFindProgram("circo|twopi|neato|fdp|dot", GeneratorPath))) {
179 std::string PSFilename = Filename + ".ps";
180
181 std::vector args;
182 args.push_back(GeneratorPath.c_str());
183 args.push_back("-Tps");
184 args.push_back("-Nfontname=Courier");
185 args.push_back("-Gsize=7.5,10");
186 args.push_back(Filename.c_str());
187 args.push_back("-o");
188 args.push_back(PSFilename.c_str());
189 args.push_back(nullptr);
190
191 errs() << "Running '" << GeneratorPath << "' program... ";
192
193 if (ExecGraphViewer(GeneratorPath, args, Filename, wait, ErrMsg))
194 return true;
195
196 args.clear();
197 args.push_back(ViewerPath.c_str());
198 switch (PSViewer) {
199 case PSV_OSXOpen:
200 args.push_back("-W");
201 args.push_back(PSFilename.c_str());
202 break;
203 case PSV_Ghostview:
204 args.push_back("--spartan");
205 args.push_back(PSFilename.c_str());
206 break;
207 case PSV_None:
208 llvm_unreachable("Invalid viewer");
209 }
210 args.push_back(nullptr);
211
212 ErrMsg.clear();
213 return ExecGraphViewer(ViewerPath, args, PSFilename, wait, ErrMsg);
214 }
215
216 // dotty
217 if (S.TryFindProgram("dotty", ViewerPath)) {
218 std::vector args;
219 args.push_back(ViewerPath.c_str());
220 args.push_back(Filename.c_str());
221 args.push_back(nullptr);
222
223 // Dotty spawns another app and doesn't wait until it returns
224 #ifdef LLVM_ON_WIN32
225 wait = false;
146226 #endif
147 #if HAVE_NEATO
148 prog = LLVM_PATH_NEATO;
149 #endif
150 #if HAVE_FDP
151 prog = LLVM_PATH_FDP;
152 #endif
153 #if HAVE_DOT
154 prog = LLVM_PATH_DOT;
155 #endif
156
157 // Find which program the user wants
158 #if HAVE_DOT
159 if (program == GraphProgram::DOT)
160 prog = LLVM_PATH_DOT;
161 #endif
162 #if (HAVE_FDP)
163 if (program == GraphProgram::FDP)
164 prog = LLVM_PATH_FDP;
165 #endif
166 #if (HAVE_NEATO)
167 if (program == GraphProgram::NEATO)
168 prog = LLVM_PATH_NEATO;
169 #endif
170 #if (HAVE_TWOPI)
171 if (program == GraphProgram::TWOPI)
172 prog = LLVM_PATH_TWOPI;
173 #endif
174 #if (HAVE_CIRCO)
175 if (program == GraphProgram::CIRCO)
176 prog = LLVM_PATH_CIRCO;
177 #endif
178
179 std::vector args;
180 args.push_back(prog.c_str());
181 args.push_back("-Tps");
182 args.push_back("-Nfontname=Courier");
183 args.push_back("-Gsize=7.5,10");
184 args.push_back(Filename.c_str());
185 args.push_back("-o");
186 args.push_back(PSFilename.c_str());
187 args.push_back(0);
188
189 errs() << "Running '" << prog << "' program... ";
190
191 if (!ExecGraphViewer(prog, args, Filename, wait, ErrMsg))
192 return;
193
194 std::string gv(LLVM_PATH_GV);
195 args.clear();
196 args.push_back(gv.c_str());
197 args.push_back(PSFilename.c_str());
198 args.push_back("--spartan");
199 args.push_back(0);
200
201 ErrMsg.clear();
202 if (!ExecGraphViewer(gv, args, PSFilename, wait, ErrMsg))
203 return;
204
205 #elif HAVE_DOTTY
206 std::string dotty(LLVM_PATH_DOTTY);
207
208 std::vector args;
209 args.push_back(dotty.c_str());
210 args.push_back(Filename.c_str());
211 args.push_back(0);
212
213 // Dotty spawns another app and doesn't wait until it returns
214 #if defined (__MINGW32__) || defined (_WINDOWS)
215 wait = false;
216 #endif
217 errs() << "Running 'dotty' program... ";
218 if (!ExecGraphViewer(dotty, args, Filename, wait, ErrMsg))
219 return;
220 #else
221 (void)Filename;
222 (void)ErrMsg;
223 #endif
224 }
227 errs() << "Running 'dotty' program... ";
228 return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
229 }
230
231 errs() << "Error: Couldn't find a usable graph viewer program:\n";
232 errs() << S.LogBuffer << "\n";
233 return true;
234 }