# findProgram -- load external program

## Synopsis

• Usage:
findProgram(name, cmd)
findProgram(name, cmds)
• Inputs:
• name, , the name of the program to load. This should match the corresponding key in programPaths.
• cmd, , a command to run that should return 0 if the program is present.
• cmds, a list, a list of commands to run that should all return 0 if the program is present.
• Optional inputs:
• RaiseError => , default value true, whether to raise an error if the program is not found.
• Verbose => , default value false, whether to inform the user of each path that is checked.
• Prefix => a list, default value {}, a list of sequences containing two strings identifying a prefix that is added to the executable binaries belonging to the program by some distributions. These sequences should be of the form (regex, prefix) where regex is a regular expression that should match all binary executables that need the prefix and prefix is the prefix itself.
• AdditionalPaths => a list, default value {}, a list of strings containing any paths to check for the program in addition to the default ones.
• MinimumVersion => , default value null, containing two strings the form (minVersion, versionCommand), where minVersion is the minimum required version of the program and versionCommand is a shell command to obtain the version number of an installed program.
• Outputs:
• an instance of the type Program, the program that was loaded. If the program is not found and RaiseError is set to false then null is returned.

## Description

This function checks for the existence of an external program by running cmd (or every element of cmds) prepended with various paths in the following order:

• The user-defined path specified by programPaths#name, if it exists.
• The path specified by prefixDirectory | currentLayout#"programs", where the programs shipped with Macaulay2 are installed.
• Each path specified by the AdditionalPaths option.
• Each path specified by the user's PATH environment variable.
• The path to M2-binary.

For each path, any prefixes specified by the Prefix option are checked.

Once this is successful (i.e., cmd or each element of cmds returns a value of 0), then a Program object is returned. If it is unsuccessful, then either an error is raised or null is returned, depending on the value of RaiseError.

Note that if a program consists of a single executable binary file, then name should coincide with the name of this file.

 i1 : programPaths#"gfan" = "/path/to/gfan/" o1 = /path/to/gfan/ i2 : gfan = findProgram("gfan", "gfan _version --help", Verbose => true) -- /path/to/gfan/gfan does not exist -- /usr/libexec/Macaulay2/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/BUILD/dan/builds.tmp/ubuntu2104-master.debug/usr-dist/x86_64-Linux-Ubuntu-21.04/bin/gfan does not exist -- /home/m2user/bin/gfan does not exist -- /usr/local/sbin/gfan does not exist -- /usr/local/bin/gfan does not exist -- /usr/sbin/gfan does not exist -- /usr/bin/gfan exists and is executable -- running "/usr/bin/gfan _version --help": This program writes out version information of the Gfan installation. -- return value: 0 o2 = gfan o2 : Program

One program that is shipped with a variety of prefixes in different distributions and for which the Prefix option is useful is TOPCOM:

 i3 : findProgram("topcom", "cube 3", Verbose => true, Prefix => { (".*", "topcom-"), ("^(cross|cube|cyclic|hypersimplex|lattice)$", "TOPCOM-"), ("^cube$", "topcom_")}) -- /usr/libexec/Macaulay2/bin/cube exists and is executable -- running "/usr/libexec/Macaulay2/bin/cube 3": [[0,0,0,1],[1,0,0,1],[0,1,0,1],[1,1,0,1],[0,0,1,1],[1,0,1,1],[0,1,1,1],[1,1,1,1]] [[7,6,5,4,3,2,1,0],[6,7,4,5,2,3,0,1],[4,6,5,7,0,2,1,3],[0,4,2,6,1,5,3,7]] -- return value: 0 o3 = topcom o3 : Program

Note that when using the MinimumVersion option, the command used to obtain the current version number must remove everything except the version number itself and any leading or trailing whitespace. Piping with standard UNIX utilities such as sed, head, tail, cut, and tr may be useful.

 i4 : findProgram("gfan", "gfan _version --help", Verbose => true, MinimumVersion => ("0.5", "gfan _version | head -2 | tail -1 | sed 's/gfan//'")) -- /path/to/gfan/gfan does not exist -- /usr/libexec/Macaulay2/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/usr-build/bin/gfan does not exist -- /home/m2user/src/M2.git/M2/BUILD/dan/builds.tmp/ubuntu2104-master.debug/usr-dist/x86_64-Linux-Ubuntu-21.04/bin/gfan does not exist -- /home/m2user/bin/gfan does not exist -- /usr/local/sbin/gfan does not exist -- /usr/local/bin/gfan does not exist -- /usr/sbin/gfan does not exist -- /usr/bin/gfan exists and is executable -- running "/usr/bin/gfan _version --help": This program writes out version information of the Gfan installation. -- return value: 0 -- found version 0.6.2 >= 0.5 o4 = gfan o4 : Program