Skip to content

Commit

Permalink
Enable configuration files in clang
Browse files Browse the repository at this point in the history
Clang is inherently a cross compiler and can generate code for any target
enabled during build. It however requires to specify many parameters in the
invocation, which could be hardcoded during configuration process in the
case of single-target compiler. The purpose of configuration files is to
make specifying clang arguments easier.

A configuration file is a collection of driver options, which are inserted
into command line before other options specified in the clang invocation.
It groups related options together and allows specifying them in simpler,
more flexible and less error prone way than just listing the options
somewhere in build scripts. Configuration file may be thought as a "macro"
that names an option set and is expanded when the driver is called.

Use of configuration files is described in `UserManual.rst`.

Differential Revision: https://reviews.llvm.org/D24933

llvm-svn: 321621
  • Loading branch information
spavloff committed Jan 1, 2018
1 parent e337268 commit 208ac65
Show file tree
Hide file tree
Showing 25 changed files with 691 additions and 12 deletions.
73 changes: 73 additions & 0 deletions clang/docs/UsersManual.rst
Expand Up @@ -694,6 +694,79 @@ a special character, which is the convention used by GNU Make. The -MV
option tells Clang to put double-quotes around the entire filename, which
is the convention used by NMake and Jom.

Configuration files
-------------------

Configuration files group command-line options and allow all of them to be
specified just by referencing the configuration file. They may be used, for
example, to collect options required to tune compilation for particular
target, such as -L, -I, -l, --sysroot, codegen options, etc.

The command line option `--config` can be used to specify configuration
file in a Clang invocation. For example:

::

clang --config /home/user/cfgs/testing.txt
clang --config debug.cfg

If the provided argument contains a directory separator, it is considered as
a file path, and options are read from that file. Otherwise the argument is
treated as a file name and is searched for sequentially in the directories:

- user directory,
- system directory,
- the directory where Clang executable resides.

Both user and system directories for configuration files are specified during
clang build using CMake parameters, CLANG_CONFIG_FILE_USER_DIR and
CLANG_CONFIG_FILE_SYSTEM_DIR respectively. The first file found is used. It is
an error if the required file cannot be found.

Another way to specify a configuration file is to encode it in executable name.
For example, if the Clang executable is named `armv7l-clang` (it may be a
symbolic link to `clang`), then Clang will search for file `armv7l.cfg` in the
directory where Clang resides.

If a driver mode is specified in invocation, Clang tries to find a file specific
for the specified mode. For example, if the executable file is named
`x86_64-clang-cl`, Clang first looks for `x86_64-cl.cfg` and if it is not found,
looks for `x86_64.cfg'.

If the command line contains options that effectively change target architecture
(these are -m32, -EL, and some others) and the configuration file starts with an
architecture name, Clang tries to load the configuration file for the effective
architecture. For example, invocation:

::

x86_64-clang -m32 abc.c

causes Clang search for a file `i368.cfg` first, and if no such file is found,
Clang looks for the file `x86_64.cfg`.

The configuration file consists of command-line options specified on one or
more lines. Lines composed of whitespace characters only are ignored as well as
lines in which the first non-blank character is `#`. Long options may be split
between several lines by a trailing backslash. Here is example of a
configuration file:

::

# Several options on line
-c --target=x86_64-unknown-linux-gnu

# Long option split between lines
-I/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../\
include/c++/5.4.0

# other config files may be included
@linux.options

Files included by `@file` directives in configuration files are resolved
relative to the including file. For example, if a configuration file
`~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
`linux.opts` is searched for in the directory `~/.llvm/os`.

Language and Target-Independent Features
========================================
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Expand Up @@ -112,6 +112,18 @@ def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
"invalid argument '%0' to -fdebug-prefix-map">;
def err_drv_malformed_sanitizer_blacklist : Error<
"malformed sanitizer blacklist: '%0'">;
def err_drv_duplicate_config : Error<
"no more than one option '--config' is allowed">;
def err_drv_config_file_not_exist : Error<
"configuration file '%0' does not exist">;
def err_drv_config_file_not_found : Error<
"configuration file '%0' cannot be found">;
def note_drv_config_file_searched_in : Note<
"was searched for in the directory: %0">;
def err_drv_cannot_read_config_file : Error<
"cannot read configuration file '%0'">;
def err_drv_nested_config_file: Error<
"option '--config' is not allowed inside configuration file">;

def err_target_unsupported_arch
: Error<"the target architecture '%0' is not supported by the target '%1'">;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Config/config.h.cmake
Expand Up @@ -35,6 +35,10 @@
/* Directories clang will search for headers */
#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"

/* Directories clang will search for configuration files */
#cmakedefine CLANG_CONFIG_FILE_SYSTEM_DIR "${CLANG_CONFIG_FILE_SYSTEM_DIR}"
#cmakedefine CLANG_CONFIG_FILE_USER_DIR "${CLANG_CONFIG_FILE_USER_DIR}"

/* Default <path> to all compiler invocations for --sysroot=<path>. */
#define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}"

Expand Down
45 changes: 37 additions & 8 deletions clang/include/clang/Driver/Driver.h
Expand Up @@ -19,21 +19,15 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/StringSaver.h"

#include <list>
#include <map>
#include <string>

namespace llvm {
class Triple;

namespace opt {
class Arg;
class ArgList;
class DerivedArgList;
class InputArgList;
class OptTable;
}
}

namespace clang {
Expand Down Expand Up @@ -138,6 +132,12 @@ class Driver {
/// The path to the compiler resource directory.
std::string ResourceDir;

/// System directory for config files.
std::string SystemConfigDir;

/// User directory for config files.
std::string UserConfigDir;

/// A prefix directory used to emulate a limited subset of GCC's '-Bprefix'
/// functionality.
/// FIXME: This type of customization should be removed in favor of the
Expand Down Expand Up @@ -208,6 +208,21 @@ class Driver {
/// Name to use when invoking gcc/g++.
std::string CCCGenericGCCName;

/// Name of configuration file if used.
std::string ConfigFile;

/// Allocator for string saver.
llvm::BumpPtrAllocator Alloc;

/// Object that stores strings read from configuration file.
llvm::StringSaver Saver;

/// Arguments originated from configuration file.
std::unique_ptr<llvm::opt::InputArgList> CfgOptions;

/// Arguments originated from command line.
std::unique_ptr<llvm::opt::InputArgList> CLOptions;

/// Whether to check that input files exist when constructing compilation
/// jobs.
unsigned CheckInputsExist : 1;
Expand Down Expand Up @@ -277,6 +292,8 @@ class Driver {
/// Name to use when invoking gcc/g++.
const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }

const std::string &getConfigFile() const { return ConfigFile; }

const llvm::opt::OptTable &getOpts() const { return *Opts; }

const DiagnosticsEngine &getDiags() const { return Diags; }
Expand Down Expand Up @@ -493,6 +510,18 @@ class Driver {
LTOKind getLTOMode() const { return LTOMode; }

private:

/// Tries to load options from configuration file.
///
/// \returns true if error occurred.
bool loadConfigFile();

/// Read options from the specified file.
///
/// \param [in] FileName File to read.
/// \returns true, if error occurred while reading.
bool readConfigFile(StringRef FileName);

/// Set the driver mode (cl, gcc, etc) from an option string of the form
/// --driver-mode=<mode>.
void setDriverModeFromOption(StringRef Opt);
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -519,6 +519,12 @@ def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-round
def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
def config : Separate<["--"], "config">, Flags<[DriverOption]>,
HelpText<"Specifies configuration file">;
def config_system_dir_EQ : Joined<["--"], "config-system-dir=">, Flags<[DriverOption, HelpHidden]>,
HelpText<"System directory for configuration files">;
def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[DriverOption, HelpHidden]>,
HelpText<"User directory for configuration files">;
def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>;
def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
def current__version : JoinedOrSeparate<["-"], "current_version">;
Expand Down

0 comments on commit 208ac65

Please sign in to comment.