Using the Slice Compiler
11 min read
2 min read
2 min read
3 min read
2 min read
4 min read
3 min read
2 min read
2 min read
Common Options
Ice provides a Slice compiler for each language mapping. The compilers share a similar command-line syntax:
slice2<name> [options] file...Regardless of which compiler you use, a number of command-line options are common to the compilers for any language mapping:
-h, --helpDisplays a help message.-v, --versionDisplays the compiler version.-DNAMEDefines the preprocessor symbolNAME.-DNAME=DEFDefines the preprocessor symbolNAMEwith the valueDEF. Each compiler always predefines the__<compiler name in upper case>__macro when compiling Slice file. For example, slice2cpp predefines__SLICE2CPP__.-UNAMEUndefines the preprocessor symbolNAME.-IDIRAdd the directoryDIRto the search path for#includedirectives.--output-dirDIRPlace the generated files into directoryDIR, which must already exist.-d, --debugPrint debug information showing the operation of the Slice parser.
--dependPrint dependency information in Makefile format to standard output by default, or to the file specified by the--depend-fileoption.
--depend-xmlPrint dependency information in XML format to standard output by default, or to the file specified by the--depend-fileoption.
--depend-jsonPrint dependency information in JSON format to standard output by default, or to the file specified by the--depend-fileoption.
--depend-file FILEDirects dependency information to the specified file. The output format depends on whether--depend,--depend-xml, or--depend-jsonis specified.--validateChecks the provided command-line options for correctness, and does not generate any code.
The Slice compilers permit you to compile more than a single source file, so you can compile several Slice definitions at once, for example:
slice2cpp -I. file1.ice file2.ice file3.iceThe Slice Compiler for C++
The Slice-to-C++ compiler (slice2cpp) offers the following additional options:
--header-ext EXT
--header-ext EXTChanges the file extension for the generated header files from the default h to the extension specified by EXT.
You can also change the header file extension with a global metadata directive:
[["cpp:header-ext:hpp"]]
// ...Only one such directive can appear in each source file. If you specify a header extension on both the command line and with a metadata directive, the metadata directive takes precedence. This ensures that included Slice files that were compiled separately get the correct header extension (provided that the included Slice files contain a corresponding metadata directive). For example:
// File example.ice#include <Ice/BuiltinSequences.ice>
// ...Compiling this file with
slice2cpp --header-ext=hpp -I/opt/Ice/include example.icegenerates example.hpp, but the #include directive in that file is for Ice/BuiltinSequences.h (not Ice/BuiltinSequences.hpp) because BuiltinSequences.ice contains the metadata directive [["cpp:header-ext:h"]].
You normally will not need to use this metadata directive. The directive is necessary only if:
- You
#includea Slice file in one of your own Slice files. - The included Slice file is part of a library you link against.
- The library ships with the included Slice file's header.
- The library header uses a different header extension than your own code.
For example, if the library uses .hpp as the header extension, but your own code uses .h, the library's Slice file should contain a [["cpp:header-ext:hpp"]] directive. (If the directive is missing, you can add it to the library's Slice file.)
--source-ext EXT
--source-ext EXTChanges the file extension for the generated source files from the default cpp to the extension specified by EXT.
--add-header HDR[,GUARD]
--add-header HDR[,GUARD]This option adds an include directive for the specified header at the beginning of the generated source file (preceding any other include directives). If GUARD is specified, the include directive is protected by the specified guard. For example, --add-header precompiled.h,__PRECOMPILED_H__ results in the following directives at the beginning of the generated source file:
#ifndef __PRECOMPILED_H__#define __PRECOMPILED_H__#include <precompiled.h>#endifThe option can be repeated to create include directives for several files.
As suggested by the preceding example, this option is useful mainly to integrate the generated code with a compiler's precompiled header mechanism.
--include-dir DIR
--include-dir DIRModifies #include directives in source files to prepend the path name of each header file with the directory DIR.
Include Directives
The #include directives generated by the Slice-to-C++ compiler can be a source of confusion if the semantics governing their generation are not well-understood. The generation of #include directives is influenced by the command-line options -I and --include-dir; these options are discussed in more detail below. The --output-dir option directs the translator to place all generated files in a particular directory, but has no impact on the contents of the generated code.
Given that the #include directives in header files and source files are generated using different semantics, we describe them in separate sections.
Header Files
In most cases, the compiler generates the appropriate #include directives by default. As an example, suppose file A.ice includes B.ice using the following statement:
// A.ice#include <B.ice>Assuming both files are in the current working directory, we run the compiler as shown below:
slice2cpp -I. A.iceThe generated file A.h contains this #include directive:
// A.h#include <B.h>If the proper include paths are specified to the C++ compiler, everything should compile correctly.
Similarly, consider the common case where A.ice includes B.ice from a subdirectory:
// A.ice#include <inc/B.ice>Assuming both files are in the inc subdirectory, we run the compiler as shown below:
slice2cpp -I. inc/A.iceThe default output of the compiler produces this #include directive in A.h:
// A.h#include <inc/B.h>Again, it is the user's responsibility to ensure that the C++ compiler is configured to find inc/B.h during compilation.
Now let us consider a more complex example, in which we do not want the #include directive in the header file to match that of the Slice file. This can be necessary when the organizational structure of the Slice files does not match the application's C++ code. In such a case, the user may need to relocate the generated files from the directory in which they were created, and the #include directives must be aligned with the new structure.
For example, let us assume that B.ice is located in the subdirectory slice/inc:
// A.ice#include <slice/inc/B.ice>However, we do not want the slice subdirectory to appear in the #include directive generated in the header file, therefore we specify the additional compiler option -Islice:
slice2cpp -I. -Islice slice/inc/A.iceThe generated code demonstrates the impact of this extra option:
// A.h#include <inc/B.h>As you can see, the #include directives generated in header files are affected by the include paths that you specify when running the compiler. Specifically, the include paths are used to abbreviate the path name in generated #include directives.
When translating an #include directive from a Slice file to a header file, the compiler compares each of the include paths against the path of the included file. If an include path matches the leading portion of the included file, the compiler removes that leading portion when generating the #include directive in the header file. If more than one include path matches, the compiler selects the one that results in the shortest path for the included file.
For example, suppose we had used the following options when compiling A.ice:
slice2cpp -I. -Islice -Islice/inc slice/inc/A.iceIn this case, the compiler compares all of the include paths against the included file slice/inc/B.ice and generates the following directive:
// A.h#include <B.h>The option -Islice/inc produces the shortest result, therefore the default path for the included file (slice/inc/B.h) is replaced with B.h.
In general, the -I option plays two roles: it enables the preprocessor to locate included Slice files, and it provides you with a certain amount of control over the generated #include directives. In the last example above, the preprocessor locates slice/inc/B.ice using the include path specified by the -I. option. The remaining -I options do not help the preprocessor locate included files; they are simply hints to the compiler.
Finally, we recommend using caution when specifying include paths. If the preprocessor is able to locate an included file via multiple include paths, it always uses the first include path that successfully locates the file. If you intend to modify the generated #include directives by specifying extra -I options, you must ensure that your include path hints match the include path selected by the preprocessor to locate the included file. As a general rule, you should avoid specifying include paths that enable the preprocessor to locate a file in multiple ways.
Source Files
By default, the compiler generates #include directives in source files using only the base name of the included file. This behavior is usually appropriate when the source file and header file reside in the same directory.
For example, suppose A.ice includes B.ice from a subdirectory, as shown in the following snippet of A.ice:
// A.ice#include <inc/B.ice>We generate the source file using this command:
slice2cpp -I. inc/A.iceUpon examination, we see that the source file contains the following #include directive:
// A.cpp#include <B.h>However, suppose that we wish to enforce a particular standard for generated #include directives so that they are compatible with our C++ compiler's existing include path settings. In this case, we use the --include-dir option to modify the generated code. For example, consider the compiler command shown below:
slice2cpp --include-dir src -I. inc/A.iceThe source file now contains the following #include directive:
// A.cpp#include <src/B.h>Any leading path in the included file is discarded as usual, and the value of the --include-dir option is prepended.
The Slice Compiler for C#
The Slice-to-C# compiler (slice2cs) supports only the common Slice compiler options.
The Slice Compiler for Java
The Slice-to-Java compiler (slice2java) offers one additional option:
--list-generatedEmit a list of generated files in XML format.
The Slice Compiler for JavaScript
The Slice-to-JavaScript compiler (slice2js) offers the following command-line options in addition to the standard options:
--stdoutPrint generated code to standard output.--typescriptGenerate TypeScript declaration file.--depend-jsonPrint dependency information in JSON format to standard output by default, or to the file specified by the--depend-fileoption. No code is generated when this option is specified. The output consists of the complete list of Slice files that the input Slice files depend on through direct or indirect inclusion.
The Slice Compiler for MATLAB
The Slice-to-MATLAB compiler (slice2matlab) offers two additional options:
--allGenerate code for all Slice definitions, including those from included files.--list-generatedEmit a list of generated files in XML format.
slice2matlab does not support the --depend flag, although it does still support --depend-xml and --depend-file.
The Slice Compiler for PHP
The Slice-to-PHP compiler (slice2php) offers one additional option:
--allGenerate code for all Slice definitions, including those from included files.
Compiler Output
For each Slice file X.ice, slice2php generates PHP code into a file named X.php in the output directory. The default output directory is the current working directory, but a different directory can be specified using the --output-dir option.
Include Files
It is important to understand how slice2php handles include files. In the absence of the --all option, the compiler does not generate PHP code for Slice definitions in included files. Rather, the compiler translates Slice #include statements into PHP require statements in the following manner:
- Determine the full pathname of the included file.
- Create the shortest possible relative pathname for the included file by iterating over each of the include directories (specified using the
-Ioption) and removing the leading directory from the included file if possible. For example, if the full pathname of an included file is/opt/App/slice/OS/Process.ice, and we specified the options-I/opt/Appand-I/opt/App/slice, then the shortest relative pathname isOS/Process.iceafter removing/opt/App/slice. - Replace the
.iceextension with.php. Continuing our example from the previous step, the translatedrequirestatement becomes
require_once "OS/Process.php";As a result, you can use -I options to tailor the require statements generated by the compiler in order to avoid absolute path names and match the organizational structure of your application's source files.
The Slice Compiler for Python
The Slice-to-Python compiler (slice2py) supports the following additional options:
--buildmodules|index|allControls what type of Python files are generated from the compile Slice files.--build=modulesGenerates only the Python module files for the Slice definitions.--build=indexGenerates only the Python package index files (init.py).--build=all. Generates both module and index files (this is the default if --build is omitted).
--list-generatedmodules|index|allLists the Python files that would be generated for the given Slice definitions, without producing any output files.--list-generated=modulesGenerates only the Python module files for the Slice definitions.--list-generated=indexGenerates only the Python package index files (init.py).--list-generated=all. Generates both module and index files (this is the default if --build is omitted).
The Slice Compiler for Swift
The Slice-to-Swift compiler (slice2swift) supports only the common Slice compiler options.