cjc
Compilation Options
This section describes some common cjc
compilation options. If an option also applies to cjc-frontend
, the option is marked with a superscript [frontend]. If the behavior of the option in cjc-frontend
is different from that of the option in cjc
, the description is added for the option.
-
An option starting with two hyphens (-) is a long option, for example,
--xxxx
. If a long option is followed by a parameter, a space or an equal sign (=) can be used between the option and parameter. For example,--xxxx <value>
is equivalent to--xxxx=<value>
. -
An option starting with a hyphen (-) is a short option, for example,
-x
. If a short option is followed by a parameter, the option and parameter can be separated by a space or not. For example,-x <value>
is equivalent to-x<value>
.
Basic Options
--output-type=[exe|staticlib|dylib]
[frontend]
Specifies the type of the output file. In exe
mode, an executable file will be generated. In staticlib
mode, a static library file (.a
file) will be generated. In dylib
mode, a dynamic library file (.so
file for Linux, .dll
file for Windows, and .dylib
file for macOS) will be generated.
By default, the exe
mode is used for cjc
.
In addition to compiling the .cj
file into an executable file, you can also compile it into a static or dynamic link library.
For example, using
$ cjc tool.cj --output-type=dylib
tool.cj
can be compiled into a dynamic link library. On the Linux platform, cjc
will generate a dynamic link library file named libtool.so
.
[frontend] In cjc-frontend
, the compilation process is performed only to the LLVM IR
. Therefore, the output is always the .bc
file. However, different --output-type
types still affect the front-end compilation policy.
--package
, -p
[frontend]
Compiles a package. If using this option, you need to specify a directory as the input. The source code files in the directory must belong to the same package.
Assume that there is the log/printer.cj
file.
package log
public func printLog(message: String) {
println("[Log]: ${message}")
}
In addition, there is the main.cj
file.
import log.*
main() {
printLog("Everything is great")
}
Using
$ cjc -p log --output-type=staticlib
To compile the log
package. cjc
will generate the liblog.a
file in the current directory.
Then, you can use the liblog.a
file to compile the main.cj
file. The compilation command is as follows:
$ cjc main.cj liblog.a
cjc
compiles main.cj
and liblog.a
into an executable file main
.
--module-name <value>
[frontend]
Specifies the name of the module to be compiled.
Assume that there is the my_module/src/log/printer.cj
file.
package log
public func printLog(message: String) {
println("[Log]: ${message}")
}
In addition, there is the main.cj
file.
import my_module.log.*
main() {
printLog("Everything is great")
}
Using
$ cjc -p my_module/src/log --module-name my_module --output-type=staticlib -o my_module/liblog.a
To compile the log
package and specify the module name as my_module
. The cjc
generates a my_module/liblog.a
file in the my_module
directory.
Then, you can use the liblog.a
file to compile the main.cj
file where the log
package is imported. The compilation command is as follows:
$ cjc main.cj my_module/liblog.a
cjc
compiles main.cj
and liblog.a
into an executable file main
.
--output <value>
, -o <value>
, -o<value>
[frontend]
Specifies the path of the output file. The output of the compiler will be written to the specified file.
For example, the following command specifies the name of the executable file that is output as a.out
:
cjc main.cj -o a.out
--library <value>
, -l <value>
, -l<value>
Specifies the library file to be linked.
The specified library file is directly transferred to the linker. Generally, this compilation option needs to be used together with --library-path <value>
.
The file name must be in the lib[arg].[extension]
format. To link the a
library, you can use the -l a
option. The linker will search for files such as liba.a
and liba.so
in the library file search paths (or search for liba.dll
when linking to the Windows target program) and links them to the final output as required.
--library-path <value>
, -L <value>
, -L<value>
Specifies the directory of the library file to be linked.
Generally, when using the --library <value>
option, you also need to use this option to specify the directory of the library file to be linked.
The path specified by --library-path <value>
will be added to the library file search paths of the linker. The path specified by the environment variable LIBRARY_PATH
will also be added to the library file search paths of the linker. The path specified by --library-path
has a higher priority than the path specified by LIBRARY_PATH
.
Assume that there is the dynamic library file libcProg.so
that is generated by compiling the following C language source file using the C language compiler.
#include <stdio.h>
void printHello() {
printf("Hello World\n");
}
In addition, there is the Cangjie file main.cj
.
foreign func printHello(): Unit
main(): Int64 {
unsafe {
printHello()
}
return 0
}
Using
cjc main.cj -L . -l cProg
To compile main.cj
and specify the cProg library to be linked. cjc
will output an executable file main
.
When main
is executed, the output is as follows:
$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
Hello World
Note that because the dynamic library file is used, you need to add the directory of the library file to $LD_LIBRARY_PATH
to ensure that main
can be dynamically linked during execution.
-g
[frontend]
Generates an executable file or library file with debugging information.
Note:
-g
can be used only with-O0
. If a higher optimization level is used, an exception may occur for the debugging function.
--trimpath <value>
[frontend]
Removes the prefix of the source file path information from the debugging information.
When compiling the Cangjie code, the cjc
saves the absolute path information of the source file (.cj
file) to provide debugging and exception information at runtime.
This option can be used to remove the specified path prefix from the source file path information. In this way, the source file path information in the file output by cjc
does not contain the specified content.
You can use --trimpath
multiple times to specify multiple different path prefixes. For each source file path, the compiler removes the first matched prefix from the path.
--coverage
[frontend]
Generates an executable program that supports code coverage statistics. The compiler generates a code information file with the suffix gcno
for each compilation unit. After the program is executed, an execution statistics file with the suffix gcda
is generated for each compilation unit. With these two files, you can use the cjcov
tool to generate the code coverage report for the current execution.
Note:
--coverage
can be used only with-O0
. If a higher optimization level is used, the compiler generates an alarm and forces-O0
to be used.--coverage
is used to compile and generate executable programs. If it is used to generate static or dynamic libraries, link errors may occur when the libraries are used.
--int-overflow=[throwing|wrapping|saturating]
[frontend]
Specifies the overflow policy for fixed-precision integer operation. The default value is throwing
.
- In the
throwing
policy, when the overflow occurs for an integer operation, an exception is thrown. - In the
wrapping
policy, the integer operation wraps to the other end of the corresponding fixed-precision integer when the overflow occurs. - In the
saturating
policy, when the overflow occurs for an integer operation, the extremum value in the corresponding fixed precision is specified as the result.
--diagnostic-format=[default|noColor|json]
[frontend]
Note:
Windows does not support the output of error information rendered in colors.
Specifies the output format of error information. The default value is default
.
default
: Error information is output in default format (with color).noColor
: Error information is output in the default format (without color).json
: Error information is output injson
format.
--verbose
, -V
[frontend]
cjc
prints the compiler version, toolchain dependency, and commands executed during compilation.
--help
, -h
[frontend]
Prints available compilation options.
When this option is used, the compiler only prints information about compilation options and does not compile any input file.
--version
, -v
[frontend]
Prints the compiler version information.
When this option is used, the compiler only prints version information and does not compile any input file.
--save-temps <value>
Saves the intermediate files generated during compilation to the directory specified by <value>
.
The compiler retains intermediate files such as .bc
, .o
generated during compilation.
--import-path <value>
[frontend]
Specifies the search path of the AST file of the imported module.
Assume that the following directory structure exists: The libs/myModule
directory contains the library file of the myModule
module and the AST export file of the log
package.
.
├── libs
| └── myModule
| ├── log.cjo
| └── libmyModule.a
└── main.cj
And there is the main.cj
file containing the following code:
import myModule.log.printLog
main() {
printLog("Everything is great")
}
You can use --import-path ./libs
to add ./libs
to the AST file search paths of the imported module. cjc
uses the ./libs/myModule/log.cjo
file to perform semantic check and compilation on the main.cj
file.
--import-path
provides the same functionality as the CANGJIE_PATH
environment variable, but the path set through --import-path
has a higher priority.
--scan-dependency
[frontend]
Uses the --scan-dependency
command to obtain the information about the direct dependency of the source code of a specified package or the cjo
file of a package on other packages and other information. The information is output in json
format.
// this file is placed under directory pkgA
macro package pkgA
import pkgB.*
import std.io.*
import pkgB.subB.*
cjc --scan-dependency --package pkgA
Or
cjc --scan-dependency pkgA.cjo
{
"package": "pkgA",
"isMacro": true,
"dependencies": [
{
"package": "pkgB",
"isStd": false,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 14
}
}
]
},
{
"package": "pkgB.subB",
"isStd": false,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 4,
"column": 1
},
"end": {
"line": 4,
"column": 19
}
}
]
},
{
"package": "std.io",
"isStd": true,
"imports": [
{
"file": "pkgA/pkgA.cj",
"begin": {
"line": 3,
"column": 1
},
"end": {
"line": 3,
"column": 16
}
}
]
}
]
}
--no-sub-pkg
[frontend]
Indicates that the current compilation package does not have subpackages.
After this option is enabled, the compiler can further reduce the code size.
--warn-off
, -Woff <value>
[frontend]
Disables all or some of the warnings that occur during compilation.
<value>
can be specified as all
or a preset warning group. If the parameter is specified as all
, the compiler does not print all warnings generated during compilation. If the parameter is specified as a preset warning group, the compiler does not print the warnings in this group generated during compilation.
When a warning is printed, a #note
line is displayed, indicating the group to which the warning belongs and how to close the warning. You can use --help
to print all available parameters of the compilation option to view the specific group names.
--warn-on
, -Won <value>
[frontend]
Enables all or some of the warnings that occur during compilation.
The value range of <value>
of --warn-on
is the same as that of <value>
of --warn-off
. --warn-on
is usually used together with --warn-off
. For example, you can set -Woff all -Won <value>
to allow only the warnings in the group specified by <value>
to be printed.
Note that the sequence of --warn-on
and --warn-off
is sensitive. For the same group, the later option overwrites the previous option. For example, if you change the positions of the two compilation options in the preceding example to -Won <value> -Woff all
, all warnings will be disabled.
--error-count-limit <value>
[frontend]
Limits the maximum number of errors printed by the compiler.
The parameter <value>
can be specified as all
or a non-negative integer. If the parameter is specified as all
, the compiler prints all errors generated during compilation. If the parameter is specified as a non-negative integer N
, the compiler prints a maximum of N
errors. The default value is 8.
--output-dir <value>
[frontend]
Controls the directory for storing intermediate files and final files generated by the compiler.
Controls the directory for storing intermediate files generated by the compiler, for example, the .cjo
files. If both --output-dir <path1>
and --output <path2>
are specified, the intermediate files are saved to <path1>
, and the final output files are saved to <path1>/<path2>
.
Note:
If this option and the
--output
option are specified at the same time, the parameter of the--output
option must be specified as a relative path.
--static-std
Statically links the std module of the Cangjie library.
This option takes effect only when the dynamic link library or executable file is compiled. By default, cjc
statically links to the std module of the Cangjie library.
--dy-std
Dynamically links the std module of the Cangjie library.
This option takes effect only when the dynamic link library or executable file is compiled.
Note:
- If the
--static-std
and--dy-std
options are used together, only the last option takes effect. - The
--dy-std
and--static-libs
options cannot be used together. Otherwise, an error is reported.
--static-libs
Statically links to non-std modules of the Cangjie library.
This option takes effect only when the dynamic link library or executable file is compiled. By default, cjc
statically links to non-std modules of the Cangjie library.
--dy-libs
Dynamically links to non-std modules of the Cangjie library.
This option takes effect only when the dynamic link library or executable file is compiled.
Note:
- If the
--static-libs
and--dy-libs
options are used together, only the last option takes effect. - The
--static-std
and--dy-libs
options cannot be used together. Otherwise, an error is reported. - If
--dy-std
is used independently, the--dy-libs
option takes effect by default and an alarm is generated. - If
--dy-libs
is used independently, the--dy-std
option takes effect by default and an alarm is generated.
--stack-trace-format=[default|simple|all]
Specifies the print format of the abnormal call stack to control the display of the stack frame information when an exception is thrown. The default format is default
.
The formats of the abnormal call stack are described as follows:
default
: The format isFunction name with generic parameters omitted (File name:Line number)
.simple
: The format isFile name:Line number
.all
: The format isComplete function name (File name:Line number)
.
--lto=[full|thin]
Enables and specifies the compilation mode of Link Time Optimization
(LTO
).
Note:
- Executable files and static libraries (
.bc
files) inLTO
mode can be compiled, but dynamic libraries cannot be compiled and generated. That is, if--output-type=dylib
is specified inLTO
mode, an error is reported during compilation. Windows
andmacOS
do not support this function.- When the
Link Time Optimization
(LTO
) compilation mode is enabled and specified, the following optimization compilation options cannot be used at the same time:-Os
and-Oz
.
LTO
supports two compilation modes:
-
--lto=full
:full LTO
merges all compilation modules into a single module for global optimization. This can maximize the optimization potential and requires longer compilation time. -
--lto=thin
: Compared withfull LTO
,thin LTO
uses parallel optimization on multiple modules and supports incremental compilation during link by default. The compilation time is shorter than that offull LTO
. Because more global information is lost, the optimization effect ofthin LTO
is not as good as that offull LTO
.- Generally, the optimization effects from high to low are as follows:
full LTO
>thin LTO
> common static link compilation. - Generally, the compilation time in descending order is as follows:
full LTO
>thin LTO
> common static link compilation.
- Generally, the optimization effects from high to low are as follows:
LTO
is used in the following scenarios:
-
Run the following command to compile the executable file:
$ cjc test.cj --lto=full or $ cjc test.cj --lto=thin
-
Run the following command to compile the static library (
.bc
file) required inLTO
mode and use the library file to compile the executable file:# The generated static library is a .bc file. $ cjc pkg.cj --lto=full --output-type=staticlib -o libpkg.bc # Input the .bc file and source file to the Cangjie compiler to compile the executable file. $ cjc test.cj libpkg.bc --lto=full
Note:
The path of the static library (
.bc
file) inLTO
mode needs to be input to the Cangjie compiler together with the file. -
In
LTO
mode, when the standard library is statically linked (--static-std
&-static-libs
), the code of the standard library also participates inLTO
optimization and is statically linked to the executable file. When the standard library is dynamically linked (--dy-std
&-dy-libs
), the dynamic library in the standard library is still used for linking inLTO
mode.# Static linking. The code of the standard library also participates in LTO optimization. $ cjc test.cj --lto=full --static-std # Dynamic linking. The dynamic library is still used for linking. The code of the standard library is not participated in LTO optimization. $ cjc test.cj --lto=full --dy-std
--pgo-instr-gen
Enables instrumentation compilation to generate an executable program that carries instrumentation information.
This function does not support the compilation of macOS targets.
Profile-guided optimization
(PGO
) is a common compilation optimization technique that uses runtime profiling information to further improve program performance. Instrumentation-based PGO
is a PGO
optimization method using instrumentation information. It usually consists of three steps:
- The compiler performs instrumentation compilation on the source code, and generates the instrumented program.
- Run the instrumented program to generate a configuration file.
- The compiler uses the configuration file to compile the source code again.
# Generate the executable program "test" that supports source code execution statistics (carrying instrumentation information).
$ cjc test.cj --pgo-instr-gen -o test
# Run the executable program "test" to generate the configuration file "test.profraw".
$ LLVM_PROFILE_FILE="test.profraw" ./test
Note:
When running the program, you can use the environment variable
LLVM_PROFILE_FILE="test%c.profraw"
to enable the continuous mode. That is, a configuration file can still be generated when the program crashes or is killed by a signal. You can use thellvm-profdata
tool to view and analyze the configuration file. However,PGO
does not support subsequent optimization steps in continuous mode.
--pgo-instr-use=<.profdata>
Uses the specified profdata
configuration file to instruct the compilation and generate an optimized executable program.
This function does not support the compilation of macOS targets.
Note:
The
--pgo-instr-use
compilation option supports only configuration files in theprofdata
format. You can use thellvm-profdata
tool to convert theprofraw
configuration file to theprofdata
configuration file.
# Convert the 'profraw' file to the 'profdata' file.
$ LD_LIBRARY_PATH=$CANGJIE_HOME/third_party/llvm/lib:$LD_LIBRARY_PATH $CANGJIE_HOME/third_party/llvm/bin/llvm-profdata merge test.profraw -o test.profdata
# Uses the specified configuration file "test.profdata" to instruct the compilation and generate an optimized executable program "testOptimized".
$ cjc test.cj --pgo-instr-use=test.profdata -o testOptimized
--target <value>
[frontend]
Specifies the triple of the target platform for compilation.
The <value>
parameter is a character string in the <arch>(-<vendor>)-<os>(-<env>)
format. Specifically:
<arch>
indicates the system architecture of the target platform, for example,aarch64
orx86_64
.<vendor>
indicates the vendor of the target platform, such aspc
orapple
. If the platform vendor is not specified or the vendor is not important, you can typeunknown
or omit this item.<os>
indicates the operating system of the target platform, for example,Linux
orWin32
.<env>
indicates the ABI or standard specifications of the target platform, which is used to distinguish different running environments of the same operating system in a finer granularity, for example,gnu
ormusl
.<env>
can be omitted when the operating system does not need to be identified in a finer granularity.
cjc
supports the following local and target platforms for cross compilation.
Local Platform (host) | Target Platform (target) |
---|---|
x86_64-linux-gnu | aarch64-hm-gnu |
Before using --target
to specify the target platform for cross compilation, prepare the cross compilation tool chain of the target platform and the corresponding Cangjie SDK version that can run on the local platform and be compiled to the target platform.
--target-cpu <value>
Note:
This option is an experimental function. The binary files generated using this option may have potential runtime problems. Pay attention to the risks of using this option. This option must be used together with the
--experimental
option.
Specifies the CPU type of the compilation target.
When the CPU type of the compilation target is specified, the compiler attempts to use the extended instruction set specific to the CPU type when generating the binary files and attempts to apply the optimization applicable to the CPU type. The binary files generated for a particular CPU type typically lose portability and may not be able to run on other CPUs (with the same architectural instruction set).
This option supports the following tested CPU types:
x86-64 architecture:
- generic
aarch64 architecture:
- generic
- tsv110
generic
is a general-purpose CPU type. When generic
is specified, the compiler generates a general instruction applicable to the architecture. In this way, the generated binary file can run on various CPU types based on the architecture on the premise that the dynamic dependency of the operating system is consistent with that of the binary file. The default value of the --target-cpu
option is generic
.
This option also supports the following CPU types. They are not tested and verified. Note that the binary files generated using the following CPU types may have runtime problems.
x86-64 architecture:
- alderlake
- amdfam10
- athlon
- athlon-4
- athlon-fx
- athlon-mp
- athlon-tbird
- athlon-xp
- athlon64
- athlon64-sse3
- atom
- barcelona
- bdver1
- bdver2
- bdver3
- bdver4
- bonnell
- broadwell
- btver1
- btver2
- c3
- c3-2
- cannonlake
- cascadelake
- cooperlake
- core-avx-i
- core-avx2
- core2
- corei7
- corei7-avx
- geode
- goldmont
- goldmont-plus
- haswell
- i386
- i486
- i586
- i686
- icelake-client
- icelake-server
- ivybridge
- k6
- k6-2
- k6-3
- k8
- k8-sse3
- knl
- knm
- lakemont
- nehalem
- nocona
- opteron
- opteron-sse3
- penryn
- pentium
- pentium-m
- pentium-mmx
- pentium2
- pentium3
- pentium3m
- pentium4
- pentium4m
- pentiumpro
- prescott
- rocketlake
- sandybridge
- sapphirerapids
- silvermont
- skx
- skylake
- skylake-avx512
- slm
- tigerlake
- tremont
- westmere
- winchip-c6
- winchip2
- x86-64
- x86-64-v2
- x86-64-v3
- x86-64-v4
- yonah
- znver1
- znver2
- znver3
aarch64 architecture:
- a64fx
- ampere1
- apple-a10
- apple-a11
- apple-a12
- apple-a13
- apple-a14
- apple-a7
- apple-a8
- apple-a9
- apple-latest
- apple-m1
- apple-s4
- apple-s5
- carmel
- cortex-a34
- cortex-a35
- cortex-a510
- cortex-a53
- cortex-a55
- cortex-a57
- cortex-a65
- cortex-a65ae
- cortex-a710
- cortex-a72
- cortex-a73
- cortex-a75
- cortex-a76
- cortex-a76ae
- cortex-a77
- cortex-a78
- cortex-a78c
- cortex-r82
- cortex-x1
- cortex-x1c
- cortex-x2
- cyclone
- exynos-m3
- exynos-m4
- exynos-m5
- falkor
- kryo
- neoverse-512tvb
- neoverse-e1
- neoverse-n1
- neoverse-n2
- neoverse-v1
- saphira
- thunderx
- thunderx2t99
- thunderx3t110
- thunderxt81
- thunderxt83
- thunderxt88
In addition to the preceding optional CPU types, this option can use native as the current CPU type. The compiler attempts to identify the CPU type of the current machine and uses the CPU type as the target type to generate binary files.
--toolchain <value>
, -B <value>
, -B<value>
Specifies the path for storing binary files in the compilation toolchain.
Binary files include C runtime target files (such as crt0.o
and crti.o
) provided by compilers, linkers, and toolchains.
After the compilation toolchain is prepared, you can save it in a customized path and transfer the path to the compiler using --toolchain <value>
. Then, the compiler can invoke the binary files in the path for cross compilation.
--sysroot <value>
Specifies the root directory of the compilation toolchain.
For a cross compilation toolchain with a fixed directory structure, if you do not need to specify other paths to binary files, dynamic libraries, and static libraries, you can use --sysroot <value>
to transfer the root directory of the toolchain to the compiler. The compiler will automatically search for required binary files, dynamic libraries, and static libraries by analyzing the directory structures based on the target platform type. If this option is used, you do not need to specify the --toolchain
and --library-path
parameters.
Assume that cross compilation is performed on the platform whose triple
is arch-os-env
, and the cross compilation toolchain has the following directory structure:
/usr/sdk/arch-os-env
├── bin
| ├── arch-os-env-gcc (Cross compiler)
| ├── arch-os-env-ld (Linker)
| └── ...
├── lib
| ├── crt1.o (Target file at C runtime)
| ├── crti.o
| ├── crtn.o
| ├── libc.so (Dynamic library)
| ├── libm.so
| └── ...
└── ...
In addition, there is the Cangjie source file hello.cj
. You can run the following command to cross-compile hello.cj
to the arch-os-env
platform:
cjc --target=arch-os-env --toolchain /usr/sdk/arch-os-env/bin --toolchain /usr/sdk/arch-os-env/lib --library-path /usr/sdk/arch-os-env/lib hello.cj -o hello
You can also use abbreviated parameters:
cjc --target=arch-os-env -B/usr/sdk/arch-os-env/bin -B/usr/sdk/arch-os-env/lib -L/usr/sdk/arch-os-env/lib hello.cj -o hello
If the directory of the toolchain complies with the common directory structure, you can run the following command without using the --toolchain
and --library-path
parameters:
cjc --target=arch-os-env --sysroot /usr/sdk/arch-os-env hello.cj -o hello
--strip-all
, -s
Deletes the symbol table in the output file during the compilation of an executable file or dynamic library.
--discard-eh-frame
Deletes some information in the eh_frame and eh_frame_hdr segments (the CRT information is not processed) during the compilation of an executable file or dynamic library. This can reduce the size of the executable file or dynamic library. However, the debugging information is affected.
This function does not support the compilation of macOS targets.
--link-options <value>
1
Specifies a linker option.
cjc
transparently transmits the parameter of this option to the linker. The available parameters vary depending on the linker (system or specified). --link-options
can be repeatedly used to specify multiple linker options.
The 1 superscript indicates that the linker transparent transmission option may vary according to the linker. For details about the supported options, see the linker document.
--disable-reflection
Disables the reflection option. That is, no reflection information is generated during compilation.
Note:
When cross compilation is performed to the aarch64-linux-ohos target, the reflection information is not generated default. This option does not take effect.
Unit Test Options
--test
[frontend]
Indicates the entry provided by the unittest
framework, which is automatically generated by the macro. When the cjc --test
option is used for compilation, the program entry is test_entry
instead of main
. For details about how to use the unittest framework, see Cangjie Programming Language Library API.
For the a.cj
file in the pkgc
directory:
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestA {
@TestCase
public func case1(): Unit {
print("case1\n")
}
}
You can run the following command in the pkgc
directory:
cjc a.cj --test
Compile a.cj
. The following information is displayed if you run main
:
Note:
The execution duration of a test case may be inconsistent each time.
case1
--------------------------------------------------------------------------------------------------
TP: default, time elapsed: 29710 ns, Result:
TCS: TestA, time elapsed: 26881 ns, RESULT:
[ PASSED ] CASE: case1 (16747 ns)
Summary: TOTAL: 1
PASSED: 1, SKIPPED: 0, ERROR: 0
FAILED: 0
--------------------------------------------------------------------------------------------------
For the following directory structure:
application
├── src
├── pkgc
| ├── a1.cj
| └── a2.cj
└── a3.cj
You can use the -p
compilation option in the application
directory to compile the entire package.
cjc pkgc --test -p
Compile the test cases a1.cj
and a2.cj
in the pkgc
package.
/*a1.cj*/
package a
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestA {
@TestCase
public func caseA(): Unit {
print("case1\n")
}
}
/*a2.cj*/
package a
import std.unittest.*
import std.unittest.testmacro.*
@Test
public class TestB {
@TestCase
public func caseB(): Unit {
throw IndexOutOfBoundsException()
}
}
When you run main
, the output is as follows (for reference only):
case1
--------------------------------------------------------------------------------------------------
TP: a, time elapsed: 367800 ns, Result:
TCS: TestA, time elapsed: 16802 ns, RESULT:
[ PASSED ] CASE: caseA (14490 ns)
TCS: TestB, time elapsed: 347754 ns, RESULT:
[ ERROR ] CASE: caseB (345453 ns)
REASON: An exception has occurred:IndexOutOfBoundsException
at std/core.Exception::init()(std/core/exception.cj:23)
at std/core.IndexOutOfBoundsException::init()(std/core/index_out_of_bounds_exception.cj:9)
at a.TestB::caseB()(/home/houle/cjtest/application/pkgc/a2.cj:7)
at a.lambda.1()(/home/houle/cjtest/application/pkgc/a2.cj:7)
at std/unittest.TestCases::execute()(std/unittest/test_case.cj:92)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:194)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:78)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:200)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:78)
at std/unittest.UT::run(std/unittest::UTestRunner)(std/unittest/test_runner.cj:200)
at std/unittest.UTestRunner::doRun()(std/unittest/test_runner.cj:75)
at std/unittest.entryMain(std/unittest::TestPackage)(std/unittest/entry_main.cj:11)
Summary: TOTAL: 2
PASSED: 1, SKIPPED: 0, ERROR: 1
FAILED: 0
--------------------------------------------------------------------------------------------------
--mock <on|off|runtime-error>
[frontend]
If on
is specified, the mock compilation is enabled for the package. This option allows classes in the package to be mocked in test cases. off
is a method for explicitly disabling mock.
Note:
The mock is automatically enabled for this package in test mode (when
--test
is enabled), and the--mock
option does not need to be explicitly passed.
runtime-error
is available only in test mode (when --test
is enabled). It allows compilation of packages with mock code, but any mock-related processing is not executed in the compiler (the processing may cause some overhead and affect the runtime performance of the test). This may be useful for the benchmark test of cases with mock code. When using this compilation option, avoid compiling cases with mock code and running tests. Otherwise, a runtime exception will be thrown.
Macro Options
cjc
supports the following macro options. For more information about the macro, see Macro.
--compile-macro
[frontend]
Compiles the macro definition file to generate the default macro definition dynamic library file.
--debug-macro
[frontend]
Generates the Cangjie code file after macro expansion. This option can be used to debug the macro expansion function.
--parallel-macro-expansion
[frontend]
Enables parallel macro expansion. This option can be used to shorten the macro expansion compilation time.
Conditional Compilation Options
cjc
supports the following conditional compilation options. For more information about conditional compilation, see Conditional Compilation.
--cfg <value>
[frontend]
Specifies a customized compilation condition.
Parallel Compilation Options
cjc
supports the following parallel compilation options for higher compilation efficiency.
--jobs <value>
, -j <value>
[frontend]
Sets the maximum number of jobs for parallel compilation. value
must be a proper positive integer. When value
is greater than the maximum parallel processing capability supported by hardware, the compiler performs parallel compilation based on the default setting calculated based on the parallel processing capability supported by the hardware.
If this compilation option is not set, the compiler performs parallel compilation based on the default setting calculated based on the parallel processing capability supported by the hardware.
Note:
--jobs 1
indicates that the compilation is performed in serial mode.
--aggressive-parallel-compile
, --apc
[frontend]
After this option is enabled, the compiler uses a more aggressive policy (which may affect optimization) to perform parallel compilation to achieve higher compilation efficiency.
Note:
In some scenarios, the
--aggressive-parallel-compile
option is forcibly enabled or disabled by the compiler.
The --aggressive-parallel-compile
option is forcibly enabled by the compiler in the following scenarios:
-O0
-g
The --aggressive-parallel-compile
option is forcibly disabled by the compiler in the following scenarios:
--fobf-string
--fobf-const
--fobf-layout
--fobf-cf-flatten
--fobf-cf-bogus
--lto
--coverage
- Compiling Windows targets
Optimization Options
--fchir-constant-propagation
[frontend]
Enables the chir constant propagation optimization.
--fno-chir-constant-propagation
[frontend]
Disables the chir constant propagation optimization.
--fchir-function-inlining
[frontend]
Enables the chir function inlining optimization.
--fno-chir-function-inlining
[frontend]
Disables the chir function inlining optimization.
--fchir-devirtualization
[frontend]
Enables the chir call devirtualization optimization.
--fno-chir-devirtualization
[frontend]
Disables the chir call devirtualization optimization.
--fast-math
[frontend]
After this option is enabled, the compiler makes fast assumption about floating-point numbers that may cause precision loss to optimize floating-point number operations.
-O<N>
[frontend]
Specifies the code optimization level with parameters.
A higher optimization level indicates that the compiler performs more code optimization to generate more efficient programs and may require longer compilation time.
By default, cjc
performs the code optimization at level O0. Currently, cjc
supports the following optimization levels: O0, O1, O2, Os, and Oz.
When the optimization level is 2, cjc
also enables the following options in addition to the corresponding optimization:
--fchir-constant-propagation
--fchir-function-inlining
--fchir-devirtualization
When the optimization level is s, cjc
also optimizes the code size in addition to O2-level optimization.
When the optimization level is z, cjc
further reduces the code size in addition to Os-level optimization.
Note:
When the optimization level is s or z, the link-time optimization compilation option
--lto=[full|thin]
cannot be used.
-O
[frontend]
Uses O1-level code optimization, which is equivalent to -O1
.
Code Obfuscation Options
cjc
supports code obfuscation, which is disabled by default, to provide extra code protection.
cjc
supports the following code obfuscation options:
--fobf-string
Enables string obfuscation.
Obfuscate strings in code so that attackers cannot statically and directly read string data in binary programs.
--fno-obf-string
Disables string obfuscation.
--fobf-const
Enables constant obfuscation.
Obfuscate constants in code by replacing numeric operation instructions with the equivalent numeric operation instruction sequence that is more complex.
--fno-obf-const
Disables constant obfuscation.
--fobf-layout
Enables layout obfuscation.
The layout obfuscation function obfuscates symbols (including function names and global variable names), path names, code line numbers, and function layout in code. After this compilation option is used, cjc
generates the symbol mapping output file *.obf.map
in the current directory. If the --obf-sym-output-mapping
option is configured, the parameter value in --obf-sym-output-mapping
is used as the name of the symbol mapping output file generated by cjc
. The symbol mapping output file contains the mapping between symbols before and after obfuscation, and can be used to de-obfuscate the obfuscated symbols.
Note:
Layout obfuscation and parallel compilation conflict with each other. Do not enable them at the same time. Otherwise, parallel compilation becomes invalid.
--fno-obf-layout
Disables layout obfuscation.
--obf-sym-prefix <string>
Specifies the prefix string added by the layout obfuscation function for symbol obfuscation.
After this option is configured, the prefix is added to all obfuscated symbols. Symbol conflicts may occur when multiple Cangjie packages are obfuscated during compilation. You can use this option to specify different prefixes for different packages to avoid symbol conflicts.
--obf-sym-output-mapping <file>
Specifies the symbol mapping output file for layout obfuscation.
The symbol mapping output file records the original symbol names, symbol names after obfuscation, and paths of the files containing symbols. The symbol mapping output file can be used to de-obfuscate the obfuscated symbols.
--obf-sym-input-mapping <file,...>
Specifies symbol mapping input files for layout obfuscation.
The layout obfuscation function uses the mapping relationships in these files to obfuscate symbols. To compile Cangjie packages with call relationships, use the symbol mapping output file of the called package as the parameter of the --obf-sym-input-mapping
option for obfuscating the calling package, ensuring that the obfuscation results of the same symbol are the same.
--obf-apply-mapping-file <file>
Provides a customized symbol mapping file for layout obfuscation. The layout obfuscation function obfuscates symbols based on the mapping in the file.
The file format is as follows:
<original_symbol_name> <new_symbol_name>
original_symbol_name
indicates the names before obfuscation, and new_symbol_name
indicates the names after obfuscation. original_symbol_name
consists of multiple field
s. field
indicates a field name, which can be a module name, package name, class name, structure name, enumeration name, function name, or variable name. field
s are separated by '.'
. If field
indicates a function name, the parameter type of the function needs to be modified with parentheses '()'
and appended to the function name. For a function without parameters, the content in the parentheses is empty. If field
has a generic parameter, use angle brackets '<>'
to add the generic parameter to the end of field
.
The layout obfuscation function replaces original_symbol_name
in Cangjie apps with new_symbol_name
. The symbols that are not in the file are replaced with random names. If the mapping specified in the file conflicts with that in --obf-sym-input-mapping
, the compiler throws an exception and stops compilation.
--fobf-export-symbols
Enables the layout obfuscation function to obfuscate export symbols. This option is enabled by default when the layout obfuscation function is enabled.
After this option is enabled, the layout obfuscation function will obfuscate the export symbols.
--fno-obf-export-symbols
Disables the layout obfuscation function from obfuscating export symbols.
--fobf-source-path
Enables the layout obfuscation function to obfuscate the path information of symbols. This option is enabled by default when the layout obfuscation function is enabled.
After this option is enabled, the layout obfuscation function obfuscates the path in the exception stack information and replaces the path name with the character string "SOURCE"
.
--fno-obf-source-path
Disables the layout obfuscation function from obfuscating the path in the stack information.
--fobf-line-number
Enables the layout obfuscation function to obfuscate the line number in the stack information. This option is enabled by default when the layout obfuscation function is enabled.
After this option is enabled, the layout obfuscation function obfuscates the line number in the exception stack information and replaces the line number with 0
.
--fno-obf-line-number
Disables the layout obfuscation function from obfuscating the line number in the stack information.
--fobf-cf-flatten
Enables control flow flattening obfuscation.
Obfuscate the control flow in the code to complicate the transfer logic.
--fno-obf-cf-flatten
Disables control flow flattening obfuscation.
--fobf-cf-bogus
Enables false control flow obfuscation.
A false control flow is inserted into the code, complicating the code logic.
--fno-obf-cf-bogus
Disables false control flow obfuscation.
--fobf-all
Enables all obfuscation functions.
Specifying this option is equivalent to specifying the following options:
--fobf-string
--fobf-const
--fobf-layout
--fobf-cf-flatten
--fobf-cf-bogus
--obf-config <file>
Specifies the path of the code obfuscation configuration file.
In the configuration file, you can disable the obfuscation tool from obfuscating some functions or symbols. The format of the configuration file is as follows:
obf_func1 name1
obf_func2 name2
...
The first parameter obf_func
indicates the specific obfuscation function as follows:
obf-cf-bogus
: False control flow obfuscationobf-cf-flatten
: Control flow flattening obfuscationobf-const
: constant obfuscationobf-layout
: layout obfuscation
The second parameter name
indicates the object to be reserved. It consists of multiple field
s. field
indicates a field name, which can be a package name, class name, structure name, enumeration name, function name, or variable name.
field
s are separated by '.'
. If field
indicates a function name, the parameter type of the function needs to be modified with parentheses '()'
and appended to the function name. For a function without parameters, the content in the parentheses is empty.
For example, assume that the packA
package contains the following code:
package packA
class MyClassA {
func funcA(a: String, b: Int64): String {
return a
}
}
To disable the control flow flattening function from obfuscating funcA
, you can write the following rule:
obf-cf-flatten packA.MyClassA.funcA(std.core.String, Int64)
You can also use wildcards to write a more flexible rule so that one rule can retain multiple objects. Currently, the following types of wildcards are supported:
Wildcards of obfuscation functions
Wildcard of Obfuscation Functions | Description |
---|---|
? | Matches a single character in names. |
* | Matches any number of characters in names. |
Wildcards of field names
Wildcard of Field Names | Description |
---|---|
? | Matches a single non-delimiter '.' character in field names. |
* | Matches any number of characters in field names, excluding separators '.' and parameters. |
** | Matches any number of characters in field names, including the separator '.' between fields and parameters. '**' takes effect only when it is used as an independent field . Otherwise, it is processed as '*' . |
Wildcards of parameter types of functions
Wildcard of Parameter Types | Description |
---|---|
... | Matches any number of parameters. |
*** | Matches a parameter of any type. |
Note:
Parameter types also consist of field names. Therefore, wildcards of field names also can be used to match a single parameter type.
Here are some examples of using wildcards:
Example 1:
obf-cf-flatten pro?.myfunc()
This rule indicates that the obf-cf-flatten
function is not allowed to obfuscate the pro?.myfunc()
function. pro?.myfunc()
can match pro0.myfunc()
but cannot match pro00.myfunc()
.
Example 2:
* pro0.**
This rule indicates that any obfuscation function is not allowed to obfuscate any function or variable in the pro0
package.
Example 3:
* pro*.myfunc(...)
This rule indicates that any obfuscation function is not allowed to obfuscate the pro*.myfunc(...)
function. pro*.myfunc(...)
can match the myfunc
function with any parameters in any single-layer package starting with pro
.
For a multi-layer package name, for example, pro0.mypack.myfunc()
, use pro*.**.myfunc(...)
for matching. Note that '**'
takes effect only when it is used as a field name. Therefore, pro**.myfunc(...)
is equivalent to pro*.myfunc(...)
and cannot be used for multi-layer package names. To match all myfunc
functions in all packages starting with pro
(including functions named myfunc
in classes), use pro*.**.myfunc(...)
.
Example 4:
obf-cf-* pro0.MyClassA.myfunc(**.MyClassB, ***, ...)
This rule indicates that the obf-cf-*
function is not allowed to obfuscate the pro0.MyClassA.myfunc(**.MyClassB, ***, ...)
function. obf-cf-*
matches the obf-cf-bogus
and obf-cf-flatten
obfuscation functions. pro0.MyClassA.myfunc(**.MyClassB, ***, ...)
matches the pro0.MyClassA.myfunc
function, where the first parameter can be of the MyClassB
type in any package, and the second parameter can be of any type and be followed by zero or more parameters.
--obf-level <value>
Specifies the obfuscation strength level.
You can specify the strength level from 1 to 9. The default strength level is 5. The larger the level number, the higher the strength. This option affects the size of the output file and the execution overhead.
--obf-seed <value>
Specifies the random seed of the obfuscation algorithm.
By specifying the random seed of the obfuscation algorithm, the same Cangjie code can have different obfuscation results in different builds. By default, the same Cangjie code has the same obfuscation result after each obfuscation.
Compiler Security Options
Note:
Windows and macOS versions do not support compiler security options.
By default, cjc
generates address-independent code and address-independent executable files when compiling executable files.
cjc
supports the following security-related linker options using --link-options
:
--link-options "-z noexecstack"
1
Sets a thread stack to be a non-executable one.
--link-options "-z relro"
1
Sets a global offset table (GOT) relocation to read-only.
--link-options "-z now"
1
Sets immediate binding.
Code Coverage Instrumentation Options
Note:
Windows and macOS versions do not support the code coverage instrumentation options.
Cangjie supports code coverage instrumentation (SanitizerCoverage, short for SanCov) and provides the same interfaces as those of LLVM SanitizerCoverage. The compiler inserts the coverage feedback function at the function or BasicBlock level. You only need to implement the specified callback function to obtain the program running status during running.
Cangjie provides the SanCov function by package. That is, a package can only be instrumented or not instrumented.
--sanitizer-coverage-level=0/1/2
Indicates the instrumentation level. The value 0 indicates that no instrumentation is performed. The value 1 indicates that function-level instrumentation is performed, that is, callback functions are inserted only at the entry of every function. The value 2 indicates that BasicBlock-level instrumentation is performed, that is, callback functions are inserted at every basic block.
If no value is specified, the value 2 is used by default.
This compilation option affects only the instrumentation levels of --sanitizer-coverage-trace-pc-guard
, --sanitizer-coverage-inline-8bit-counters
, and --sanitizer-coverage-inline-bool-flag
.
--sanitizer-coverage-trace-pc-guard
After this option is enabled, the function call __sanitizer_cov_trace_pc_guard(uint32_t *guard_variable)
is inserted on every edge. The option is affected by sanitizer-coverage-level
.
Note that the implementation of this function is different from that of gcc/llvm: void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop)
is not inserted to a constructor; instead the function call uint32_t *__cj_sancov_pc_guard_ctor(uint64_t edgeCount)
is inserted during package initialization.
The callback function __cj_sancov_pc_guard_ctor
needs to be implemented by developers. The package with SanCov enabled calls the callback function as early as possible. The input parameter is the number of edges of the package, and the return value is the memory area created by the calloc function.
To call __sanitizer_cov_trace_pc_guard_init
, you are advised to call it in __cj_sancov_pc_guard_ctor
and use the dynamically created buffer to calculate the input parameter and return value of the function.
A standard __cj_sancov_pc_guard_ctor
reference implementation is as follows:
uint32_t *__cj_sancov_pc_guard_ctor(uint64_t edgeCount) {
uint32_t *p = (uint32_t *) calloc(edgeCount, sizeof(uint32_t));
__sanitizer_cov_trace_pc_guard_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-inline-8bit-counters
After this option is enabled, an accumulator is inserted on every edge and the accumulator is incremented by 1 for the experienced edge. The option is affected by sanitizer-coverage-level
.
Note that the implementation of this function is different from that of gcc/llvm: void __sanitizer_cov_8bit_counters_init(char *start, char *stop)
is not inserted to a constructor; instead the function call uint8_t *__cj_sancov_8bit_counters_ctor(uint64_t edgeCount)
is inserted during package initialization.
The callback function __cj_sancov_pc_guard_ctor
needs to be implemented by developers. The package with SanCov enabled calls the callback function as early as possible. The input parameter is the number of edges of the package, and the return value is the memory area created by the calloc function.
To call __sanitizer_cov_8bit_counters_init
, you are advised to call it in __cj_sancov_8bit_counters_ctor
and use the dynamically created buffer to calculate the input parameter and return value of the function.
A standard __cj_sancov_8bit_counters_ctor
reference implementation is as follows:
uint8_t *__cj_sancov_8bit_counters_ctor(uint64_t edgeCount) {
uint8_t *p = (uint8_t *) calloc(edgeCount, sizeof(uint8_t));
__sanitizer_cov_8bit_counters_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-inline-bool-flag
After this option is enabled, a boolean value is inserted on every edge and the boolean value is set to True for the experienced edge. The option is affected by sanitizer-coverage-level
.
Note that the implementation of this function is different from that of gcc/llvm: void __sanitizer_cov_bool_flag_init(bool *start, bool *stop)
is not inserted to a constructor; instead the function call bool *__cj_sancov_bool_flag_ctor(uint64_t edgeCount)
is inserted during package initialization.
The callback function __cj_sancov_bool_flag_ctor
needs to be implemented by developers. The package with SanCov enabled calls the callback function as early as possible. The input parameter is the number of edges of the package, and the return value is the memory area created by the calloc function.
To call __sanitizer_cov_bool_flag_init
, you are advised to call it in __cj_sancov_bool_flag_ctor
and use the dynamically created buffer to calculate the input parameter and return value of the function.
A standard __cj_sancov_bool_flag_ctor
reference implementation is as follows:
bool *__cj_sancov_bool_flag_ctor(uint64_t edgeCount) {
bool *p = (bool *) calloc(edgeCount, sizeof(bool));
__sanitizer_cov_bool_flag_init(p, p + edgeCount);
return p;
}
--sanitizer-coverage-pc-table
This compilation option provides the mapping between instrumentation points and source code. Currently, only the function-level mapping is provided. This option must work with --sanitizer-coverage-trace-pc-guard
, --sanitizer-coverage-inline-8bit-counters
, and --sanitizer-coverage-inline-bool-flag
options, and requires one or more of the options to be enabled at the same time.
Note that the implementation of this function is different from that of gcc/llvm: void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, const uintptr_t *pcs_end);
is not inserted to a constructor; instead the function call void __cj_sancov_pcs_init(int8_t *packageName, uint64_t n, int8_t **funcNameTable, int8_t **fileNameTable, uint64_t *lineNumberTable)
is inserted during package initialization. The input parameters are described as follows:
int8_t *packageName
: package name, which is a character string. (The instrumentation uses the C-style int8 array as the input parameter to express the character string, same as below.)uint64_t n
: indicates that n functions are instrumented.int8_t **funcNameTable
: string array whose length is n. The function name corresponding to the ith instrumentation point is funcNameTable[i].int8_t **fileNameTable
: string array whose length is n. The file name corresponding to the ith instrumentation point is fileNameTable[i].uint64_t *lineNumberTable
: uint64 array whose length is n. The line number corresponding to the ith instrumentation point is lineNumberTable[i].
To call __sanitizer_cov_pcs_init
, you need to convert Cangjie pc-table to C pc-table.
--sanitizer-coverage-stack-depth
After this compilation option is enabled, the SP pointer can be obtained only that the call __updateSancovStackDepth
is inserted at every function entry and implemented in C, because Cangjie cannot obtain the SP pointer.
A standard updateSancovStackDepth
implementation is as follows:
thread_local void* __sancov_lowest_stack;
void __updateSancovStackDepth()
{
register void* sp = __builtin_frame_address(0);
if (sp < __sancov_lowest_stack) {
__sancov_lowest_stack = sp;
}
}
--sanitizer-coverage-trace-compares
After this option is enabled, the function callback functions are inserted before all compare and match instructions are called. The following are the function lists, which are the same as the API functions of LLVM. For details, see Tracing data flow.
void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2);
void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2);
void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2);
void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2);
void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2);
void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2);
void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2);
void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2);
void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases);
--sanitizer-coverage-trace-memcmp
Feeds back prefix comparison information in String and Array comparisons. If this option is enabled, a callback function is inserted before the comparison functions of String and Array. Specifically, the corresponding stub functions will be inserted for the following APIs of String and Array:
- String==: __sanitizer_weak_hook_memcmp
- String.startsWith: __sanitizer_weak_hook_memcmp
- String.endsWith: __sanitizer_weak_hook_memcmp
- String.indexOf: __sanitizer_weak_hook_strstr
- String.replace: __sanitizer_weak_hook_strstr
- String.contains: __sanitizer_weak_hook_strstr
- CString==: __sanitizer_weak_hook_strcmp
- CString.startswith: __sanitizer_weak_hook_memcmp
- CString.endswith: __sanitizer_weak_hook_strncmp
- CString.compare: __sanitizer_weak_hook_strcmp
- CString.equalsLower: __sanitizer_weak_hook_strcasecmp
- Array==: __sanitizer_weak_hook_memcmp
- ArrayList==: __sanitizer_weak_hook_memcmp
Experimental Function Options
--experimental
[frontend]
Enables the experimental function to allow other experimental function options to be used on the command line.
Note:
Binary files generated using the experimental function may have potential runtime problems. Pay attention to the risks of using this option.
Other Functions
Coloring the error information of the compiler
For the Cangjie compiler for Windows, the error information is colored only when the compiler runs Windows 10 version 1511(Build 10586) or later.
Setting build-id
--link-options "--build-id=<arg>"
1 can be used to transparently transmit the linker options to set build-id.
This function is unavailable to compile Windows targets.
Setting rpath
--link-options "-rpath=<arg>"
1 can be used to transparently transmit the linker options to set rpath.
This function is unavailable to compile Windows targets.
Incremental compilation
--incremental-compile
[frontend] can be used to enable incremental compilation. After this function is enabled, cjc
accelerates the compilation based on the cache file of the previous compilation.
Environment Variables Used by cjc
Here describe the environment variables that may be used by the Cangjie compiler during code compilation.
TMPDIR
or TMP
The Cangjie compiler saves the temporary files generated during compilation to a temporary directory. By default, the files are saved in the /tmp
directory for the Linux
and macOS
operating systems, and in the C:\Windows\Temp
directory for the Windows
operating system. The Cangjie compiler also allows you to set the directory of temporary files. On the Linux
and macOS
operating systems, you can set the environment variable TMPDIR
to change the directory of temporary files. On the Windows
operating system, you can set the environment variable TMP
to change the directory of temporary files.
For example: In Linux shell
export TMPDIR=/home/xxxx
In Windows cmd
set TMP=D:\\xxxx