View Source Autoconfex (Autoconfex v0.1.0)

Autoconfex: Auto-configuration of NIFs in C for Elixir.

Summary

Functions

Returns true if the given executable can compile the given source_code, which will be created on the path joining /tmp and base, with the given args.

Returns true if the given c_compiler can compile the given source_code with the given options.

Execute the given executable with args, if the executable can be located on the system.

Functions

compilable?(executable, base, source_code, args)

@spec compilable?(binary(), binary(), binary(), [binary()]) :: boolean()

Returns true if the given executable can compile the given source_code, which will be created on the path joining /tmp and base, with the given args.

compilable_by_cc?(c_compiler, source_code, options \\ [])

@spec compilable_by_cc?(binary(), binary(), [binary()]) :: boolean()

Returns true if the given c_compiler can compile the given source_code with the given options.

c_compiler assumes to be option-compatible with GCC and Clang.

Examples

iex> Autoconfex.compilable_by_cc?(
...>   "gcc",
...>   """
...>   int main(int argc, char *argv[])
...>   {
...>      return 0;
...>   }
...>   """
...> )
true

execute(executable, args, opts \\ [])

Execute the given executable with args, if the executable can be located on the system.

executable is expected to be an executable available in PATH unless an absolute path is given.

args must be a list of binaries which the executable will receive as its arguments as is. This means that:

  • environment variables will not be interpolated
  • wildcard expansion will not happen (unless Path.wildcard/2 is used explicitly)
  • arguments do not need to be escaped or quoted for shell safety

This function returns a tuple containing the collected result and the command exit status.

Internally, this function uses a Port for interacting with the outside world. However, if you plan to run a long-running program, ports guarantee stdin/stdout devices will be closed but it does not automatically terminate the program. The documentation for the Port module describes this problem and possible solutions under the "Zombie processes" section.

Windows argument splitting and untrusted arguments

On Unix systems, arguments are passed to a new operating system process as an array of strings but on Windows it is up to the child process to parse them and some Windows programs may apply their own rules, which are inconsistent with the standard C runtime argv parsing

This is particularly troublesome when invoking .bat or .com files as these run implicitly through cmd.exe, whose argument parsing is vulnerable to malicious input and can be used to run arbitrary shell commands.

Therefore, if you are running on Windows and you execute batch files or .com applications, you must not pass untrusted input as arguments to the program. You may avoid accidentally executing them by explicitly passing the extension of the program you want to run, such as .exe, and double check the program is indeed not a batch file or .com application.

Options

  • :into - injects the result into the given collectable, defaults to ""

  • :lines - (since v1.15.0) reads the output by lines instead of in bytes. It expects a number of maximum bytes to buffer internally (1024 is a reasonable default). The collectable will be called with each finished line (regardless of buffer size) and without the EOL character

  • :cd - the directory to run the command in

  • :env - an enumerable of tuples containing environment key-value as binary. The child process inherits all environment variables from its parent process, the Elixir application, except those overwritten or cleared using this option. Specify a value of nil to clear (unset) an environment variable, which is useful for preventing credentials passed to the application from leaking into child processes

  • :arg0 - sets the command arg0

  • :stderr_to_stdout - redirects stderr to stdout when true, no effect if use_stdio is false.

  • :use_stdio - true by default, setting it to false allows direct interaction with the terminal from the callee

  • :parallelism - when true, the VM will schedule port tasks to improve parallelism in the system. If set to false, the VM will try to perform commands immediately, improving latency at the expense of parallelism. The default is false, and can be set on system startup by passing the +spp flag to --erl. Use :erlang.system_info(:port_parallelism) to check if enabled.

Error reasons

If invalid arguments are given, ArgumentError is raised by System.cmd/3. System.cmd/3 also expects a strict set of options and will raise if unknown or invalid options are given.

Furthermore, System.cmd/3 may fail with one of the POSIX reasons detailed below:

  • :system_limit - all available ports in the Erlang emulator are in use

  • :enomem - there was not enough memory to create the port

  • :eagain - there are no more available operating system processes

  • :enametoolong - the external command given was too long

  • :emfile - there are no more available file descriptors (for the operating system process that the Erlang emulator runs in)

  • :enfile - the file table is full (for the entire operating system)

  • :eacces - the command does not point to an executable file

  • :enoent - the command does not point to an existing file