mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib, --lib, and --bin flags from rustc, adding the following flags: * --emit=[asm,ir,bc,obj,link] * --crate-type=[dylib,rlib,staticlib,bin,lib] The -o option has also been redefined to be used for *all* flavors of outputs. This means that we no longer ignore it for libraries. The --out-dir remains the same as before. The new logic for files that rustc emits is as follows: 1. Output types are dictated by the --emit flag. The default value is --emit=link, and this option can be passed multiple times and have all options stacked on one another. 2. Crate types are dictated by the --crate-type flag and the #[crate_type] attribute. The flags can be passed many times and stack with the crate attribute. 3. If the -o flag is specified, and only one output type is specified, the output will be emitted at this location. If more than one output type is specified, then the filename of -o is ignored, and all output goes in the directory that -o specifies. The -o option always ignores the --out-dir option. 4. If the --out-dir flag is specified, all output goes in this directory. 5. If -o and --out-dir are both not present, all output goes in the current directory of the process. 6. When multiple output types are specified, the filestem of all output is the same as the name of the CrateId (derived from a crate attribute or from the filestem of the crate file). Closes #7791 Closes #11056 Closes #11667
This commit is contained in:
parent
f039d10cf7
commit
6e7968b10a
24
man/rustc.1
24
man/rustc.1
@ -12,17 +12,14 @@ This program is a compiler for the Rust language, available at
|
|||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-bin\fR
|
\fB\-\-crate-type=[bin|lib|dylib|rlib|staticlib]\fR
|
||||||
Compile an executable crate (default)
|
Configure the flavor of rust crate that is generated (default `bin`)
|
||||||
.TP
|
|
||||||
\fB\-c\fR
|
|
||||||
Compile and assemble, but do not link
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-cfg\fR SPEC
|
\fB\-\-cfg\fR SPEC
|
||||||
Configure the compilation environment
|
Configure the compilation environment
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-emit\-llvm\fR
|
\fB\-\-emit=[asm,ir,bc,obj,link]\fR
|
||||||
Produce an LLVM bitcode file
|
Configure the output that rustc will produce
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-help\fR
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
Display this message
|
Display this message
|
||||||
@ -30,9 +27,6 @@ Display this message
|
|||||||
\fB\-L\fR PATH
|
\fB\-L\fR PATH
|
||||||
Add a directory to the library search path
|
Add a directory to the library search path
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-lib\fR
|
|
||||||
Compile a library crate
|
|
||||||
.TP
|
|
||||||
\fB\-\-linker\fR LINKER
|
\fB\-\-linker\fR LINKER
|
||||||
Program to use for linking instead of the default
|
Program to use for linking instead of the default
|
||||||
.TP
|
.TP
|
||||||
@ -49,7 +43,7 @@ Run all passes except translation; no output
|
|||||||
Equivalent to \fI\-\-opt\-level=2\fR
|
Equivalent to \fI\-\-opt\-level=2\fR
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR FILENAME
|
\fB\-o\fR FILENAME
|
||||||
Write output to <filename>
|
Write output to <filename>. Ignored if more than one --emit is specified.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-opt\-level\fR LEVEL
|
\fB\-\-opt\-level\fR LEVEL
|
||||||
Optimize with possible levels 0-3
|
Optimize with possible levels 0-3
|
||||||
@ -60,7 +54,8 @@ the default passes for the optimization level. A value of 'list'
|
|||||||
will list the available passes.
|
will list the available passes.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-out\-dir\fR DIR
|
\fB\-\-out\-dir\fR DIR
|
||||||
Write output to compiler-chosen filename in <dir>
|
Write output to compiler-chosen filename in <dir>. Ignored if -o is specified.
|
||||||
|
(default the current directory)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-parse\-only\fR
|
\fB\-\-parse\-only\fR
|
||||||
Parse only; do not compile, assemble, or link
|
Parse only; do not compile, assemble, or link
|
||||||
@ -71,9 +66,6 @@ Pretty-print the input instead of compiling; valid types are: normal
|
|||||||
expanded, with type annotations), or identified (fully parenthesized,
|
expanded, with type annotations), or identified (fully parenthesized,
|
||||||
AST nodes and blocks with IDs)
|
AST nodes and blocks with IDs)
|
||||||
.TP
|
.TP
|
||||||
\fB\-S\fR
|
|
||||||
Compile only; do not assemble or link
|
|
||||||
.TP
|
|
||||||
\fB\-\-save\-temps\fR
|
\fB\-\-save\-temps\fR
|
||||||
Write intermediate files (.bc, .opt.bc, .o) in addition to normal output
|
Write intermediate files (.bc, .opt.bc, .o) in addition to normal output
|
||||||
.TP
|
.TP
|
||||||
@ -120,7 +112,7 @@ To build an executable from a source file with a main function:
|
|||||||
$ rustc -o hello hello.rs
|
$ rustc -o hello hello.rs
|
||||||
|
|
||||||
To build a library from a source file:
|
To build a library from a source file:
|
||||||
$ rustc --lib hello-lib.rs
|
$ rustc --crate-type=lib hello-lib.rs
|
||||||
|
|
||||||
To build either with a crate (.rs) file:
|
To build either with a crate (.rs) file:
|
||||||
$ rustc hello.rs
|
$ rustc hello.rs
|
||||||
|
@ -102,7 +102,7 @@ $(foreach crate,$(CRATES),$(eval $(call RUST_CRATE,$(crate))))
|
|||||||
#
|
#
|
||||||
# $(1) is the crate to generate variables for
|
# $(1) is the crate to generate variables for
|
||||||
define RUST_TOOL
|
define RUST_TOOL
|
||||||
TOOL_INPUTS_$(1) := $$(wildcard $$(addprefix $(S)$$(dir $$(TOOL_SOURCE_$(1))), \
|
TOOL_INPUTS_$(1) := $$(wildcard $$(addprefix $$(dir $$(TOOL_SOURCE_$(1))), \
|
||||||
*.rs */*.rs */*/*.rs */*/*/*.rs))
|
*.rs */*.rs */*/*.rs */*/*/*.rs))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ $$(TLIB2_T_$(2)_H_$(3))/$$(FT_LIB): \
|
|||||||
tmp/$$(FT).rc \
|
tmp/$$(FT).rc \
|
||||||
$$(SREQ2_T_$(2)_H_$(3))
|
$$(SREQ2_T_$(2)_H_$(3))
|
||||||
@$$(call E, compile_and_link: $$@)
|
@$$(call E, compile_and_link: $$@)
|
||||||
$$(STAGE2_T_$(2)_H_$(3)) --lib -o $$@ $$< \
|
$$(STAGE2_T_$(2)_H_$(3)) --crate-type=dylib --out-dir $$(@D) $$< \
|
||||||
-L "$$(RT_OUTPUT_DIR_$(2))"
|
-L "$$(RT_OUTPUT_DIR_$(2))"
|
||||||
|
|
||||||
$(3)/test/$$(FT_DRIVER)-$(2)$$(X_$(2)): \
|
$(3)/test/$$(FT_DRIVER)-$(2)$$(X_$(2)): \
|
||||||
|
@ -245,7 +245,7 @@ actual:\n\
|
|||||||
};
|
};
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let mut args = ~[~"-",
|
let mut args = ~[~"-",
|
||||||
~"--no-trans", ~"--lib",
|
~"--no-trans", ~"--crate-type=lib",
|
||||||
~"--target=" + target,
|
~"--target=" + target,
|
||||||
~"-L", config.build_base.as_str().unwrap().to_owned(),
|
~"-L", config.build_base.as_str().unwrap().to_owned(),
|
||||||
~"-L",
|
~"-L",
|
||||||
@ -659,7 +659,7 @@ fn compile_test_(config: &config, props: &TestProps,
|
|||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
|
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
|
||||||
let args = make_compile_args(config, props, link_args + extra_args,
|
let args = make_compile_args(config, props, link_args + extra_args,
|
||||||
make_exe_name, testfile);
|
|a, b| ThisFile(make_exe_name(a, b)), testfile);
|
||||||
compose_and_run_compiler(config, props, testfile, args, None)
|
compose_and_run_compiler(config, props, testfile, args, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,8 +702,12 @@ fn compose_and_run_compiler(
|
|||||||
let abs_ab = config.aux_base.join(rel_ab.as_slice());
|
let abs_ab = config.aux_base.join(rel_ab.as_slice());
|
||||||
let aux_props = load_props(&abs_ab);
|
let aux_props = load_props(&abs_ab);
|
||||||
let aux_args =
|
let aux_args =
|
||||||
make_compile_args(config, &aux_props, ~[~"--dylib"] + extra_link_args,
|
make_compile_args(config, &aux_props, ~[~"--crate-type=dylib"]
|
||||||
|a,b| make_lib_name(a, b, testfile), &abs_ab);
|
+ extra_link_args,
|
||||||
|
|a,b| {
|
||||||
|
let f = make_lib_name(a, b, testfile);
|
||||||
|
ThisDirectory(f.dir_path())
|
||||||
|
}, &abs_ab);
|
||||||
let auxres = compose_and_run(config, &abs_ab, aux_args, ~[],
|
let auxres = compose_and_run(config, &abs_ab, aux_args, ~[],
|
||||||
config.compile_lib_path, None);
|
config.compile_lib_path, None);
|
||||||
if !auxres.status.success() {
|
if !auxres.status.success() {
|
||||||
@ -741,10 +745,15 @@ fn compose_and_run(config: &config, testfile: &Path,
|
|||||||
prog, args, procenv, input);
|
prog, args, procenv, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TargetLocation {
|
||||||
|
ThisFile(Path),
|
||||||
|
ThisDirectory(Path),
|
||||||
|
}
|
||||||
|
|
||||||
fn make_compile_args(config: &config,
|
fn make_compile_args(config: &config,
|
||||||
props: &TestProps,
|
props: &TestProps,
|
||||||
extras: ~[~str],
|
extras: ~[~str],
|
||||||
xform: |&config, &Path| -> Path,
|
xform: |&config, &Path| -> TargetLocation,
|
||||||
testfile: &Path)
|
testfile: &Path)
|
||||||
-> ProcArgs {
|
-> ProcArgs {
|
||||||
let xform_file = xform(config, testfile);
|
let xform_file = xform(config, testfile);
|
||||||
@ -755,10 +764,14 @@ fn make_compile_args(config: &config,
|
|||||||
};
|
};
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let mut args = ~[testfile.as_str().unwrap().to_owned(),
|
let mut args = ~[testfile.as_str().unwrap().to_owned(),
|
||||||
~"-o", xform_file.as_str().unwrap().to_owned(),
|
|
||||||
~"-L", config.build_base.as_str().unwrap().to_owned(),
|
~"-L", config.build_base.as_str().unwrap().to_owned(),
|
||||||
~"--target=" + target]
|
~"--target=" + target]
|
||||||
+ extras;
|
+ extras;
|
||||||
|
let path = match xform_file {
|
||||||
|
ThisFile(path) => { args.push(~"-o"); path }
|
||||||
|
ThisDirectory(path) => { args.push(~"--out-dir"); path }
|
||||||
|
};
|
||||||
|
args.push(path.as_str().unwrap().to_owned());
|
||||||
args.push_all_move(split_maybe_args(&config.rustcflags));
|
args.push_all_move(split_maybe_args(&config.rustcflags));
|
||||||
args.push_all_move(split_maybe_args(&props.compile_flags));
|
args.push_all_move(split_maybe_args(&props.compile_flags));
|
||||||
return ProcArgs {prog: config.rustc_path.as_str().unwrap().to_owned(), args: args};
|
return ProcArgs {prog: config.rustc_path.as_str().unwrap().to_owned(), args: args};
|
||||||
@ -1043,10 +1056,10 @@ fn compile_test_and_save_bitcode(config: &config, props: &TestProps,
|
|||||||
let aux_dir = aux_output_dir_name(config, testfile);
|
let aux_dir = aux_output_dir_name(config, testfile);
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
|
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
|
||||||
let llvm_args = ~[~"-c", ~"--lib", ~"--save-temps"];
|
let llvm_args = ~[~"--emit=obj", ~"--crate-type=lib", ~"--save-temps"];
|
||||||
let args = make_compile_args(config, props,
|
let args = make_compile_args(config, props,
|
||||||
link_args + llvm_args,
|
link_args + llvm_args,
|
||||||
make_o_name, testfile);
|
|a, b| ThisFile(make_o_name(a, b)), testfile);
|
||||||
compose_and_run_compiler(config, props, testfile, args, None)
|
compose_and_run_compiler(config, props, testfile, args, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3678,43 +3678,43 @@ found in the [ffi tutorial][ffi].
|
|||||||
In one session of compilation, the compiler can generate multiple artifacts
|
In one session of compilation, the compiler can generate multiple artifacts
|
||||||
through the usage of command line flags and the `crate_type` attribute.
|
through the usage of command line flags and the `crate_type` attribute.
|
||||||
|
|
||||||
* `--bin`, `#[crate_type = "bin"]` - A runnable executable will be produced.
|
* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be
|
||||||
This requires that there is a `main` function in the crate which will be run
|
produced. This requires that there is a `main` function in the crate which
|
||||||
when the program begins executing. This will link in all Rust and native
|
will be run when the program begins executing. This will link in all Rust and
|
||||||
dependencies, producing a distributable binary.
|
native dependencies, producing a distributable binary.
|
||||||
|
|
||||||
* `--lib`, `#[crate_type = "lib"]` - A Rust library will be produced. This is
|
* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced.
|
||||||
an ambiguous concept as to what exactly is produced because a library can
|
This is an ambiguous concept as to what exactly is produced because a library
|
||||||
manifest itself in several forms. The purpose of this generic `lib` option is
|
can manifest itself in several forms. The purpose of this generic `lib` option
|
||||||
to generate the "compiler recommended" style of library. The output library
|
is to generate the "compiler recommended" style of library. The output library
|
||||||
will always be usable by rustc, but the actual type of library may change
|
will always be usable by rustc, but the actual type of library may change from
|
||||||
from time-to-time. The remaining output types are all different flavors of
|
time-to-time. The remaining output types are all different flavors of
|
||||||
libraries, and the `lib` type can be seen as an alias for one of them (but
|
libraries, and the `lib` type can be seen as an alias for one of them (but the
|
||||||
the actual one is compiler-defined).
|
actual one is compiler-defined).
|
||||||
|
|
||||||
* `--dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will be
|
* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will
|
||||||
produced. This is different from the `lib` output type in that this forces
|
be produced. This is different from the `lib` output type in that this forces
|
||||||
dynamic library generation. The resulting dynamic library can be used as a
|
dynamic library generation. The resulting dynamic library can be used as a
|
||||||
dependency for other libraries and/or executables. This output type will
|
dependency for other libraries and/or executables. This output type will
|
||||||
create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on
|
create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on
|
||||||
windows.
|
windows.
|
||||||
|
|
||||||
* `--staticlib`, `#[crate_type = "staticlib"]` - A static system library will
|
* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system
|
||||||
be produced. This is different from other library outputs in that the Rust
|
library will be produced. This is different from other library outputs in that
|
||||||
compiler will never attempt to link to `staticlib` outputs. The purpose of
|
the Rust compiler will never attempt to link to `staticlib` outputs. The
|
||||||
this output type is to create a static library containing all of the local
|
purpose of this output type is to create a static library containing all of
|
||||||
crate's code along with all upstream dependencies. The static library is
|
the local crate's code along with all upstream dependencies. The static
|
||||||
actually a `*.a` archive on linux and osx and a `*.lib` file on windows. This
|
library is actually a `*.a` archive on linux and osx and a `*.lib` file on
|
||||||
format is recommended for use in situtations such as linking Rust code into an
|
windows. This format is recommended for use in situtations such as linking
|
||||||
existing non-Rust application because it will not have dynamic dependencies on
|
Rust code into an existing non-Rust application because it will not have
|
||||||
other Rust code.
|
dynamic dependencies on other Rust code.
|
||||||
|
|
||||||
* `--rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be produced.
|
* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be
|
||||||
This is used as an intermediate artifact and can be thought of as a "static
|
produced. This is used as an intermediate artifact and can be thought of as a
|
||||||
Rust library". These `rlib` files, unlike `staticlib` files, are interpreted
|
"static Rust library". These `rlib` files, unlike `staticlib` files, are
|
||||||
by the Rust compiler in future linkage. This essentially means that `rustc`
|
interpreted by the Rust compiler in future linkage. This essentially means
|
||||||
will look for metadata in `rlib` files like it looks for metadata in dynamic
|
that `rustc` will look for metadata in `rlib` files like it looks for metadata
|
||||||
libraries. This form of output is used to produce statically linked
|
in dynamic libraries. This form of output is used to produce statically linked
|
||||||
executables as well as `staticlib` outputs.
|
executables as well as `staticlib` outputs.
|
||||||
|
|
||||||
Note that these outputs are stackable in the sense that if multiple are
|
Note that these outputs are stackable in the sense that if multiple are
|
||||||
@ -3769,9 +3769,9 @@ dependencies will be used:
|
|||||||
then the compiler will force all dependencies to be dynamic and will generate
|
then the compiler will force all dependencies to be dynamic and will generate
|
||||||
errors if dynamic versions could not be found.
|
errors if dynamic versions could not be found.
|
||||||
|
|
||||||
In general, `--bin` or `--lib` should be sufficient for all compilation needs,
|
In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
|
||||||
and the other options are just available if more fine-grained control is desired
|
all compilation needs, and the other options are just available if more
|
||||||
over the output format of a Rust crate.
|
fine-grained control is desired over the output format of a Rust crate.
|
||||||
|
|
||||||
### Logging system
|
### Logging system
|
||||||
|
|
||||||
|
@ -3162,8 +3162,8 @@ fn main() { println!("hello {}", world::explore()); }
|
|||||||
Now compile and run like this (adjust to your platform if necessary):
|
Now compile and run like this (adjust to your platform if necessary):
|
||||||
|
|
||||||
~~~~ {.notrust}
|
~~~~ {.notrust}
|
||||||
> rustc --lib world.rs # compiles libworld-<HASH>-0.42.so
|
> rustc --crate-type=lib world.rs # compiles libworld-<HASH>-0.42.so
|
||||||
> rustc main.rs -L . # compiles main
|
> rustc main.rs -L . # compiles main
|
||||||
> ./main
|
> ./main
|
||||||
"hello world"
|
"hello world"
|
||||||
~~~~
|
~~~~
|
||||||
|
@ -7,18 +7,15 @@ typeset -A opt_args
|
|||||||
_rustc_opts_switches=(
|
_rustc_opts_switches=(
|
||||||
--android-cross-path'[The path to the Android NDK]'
|
--android-cross-path'[The path to the Android NDK]'
|
||||||
--ar'[Program to use for managing archives instead of the default.]'
|
--ar'[Program to use for managing archives instead of the default.]'
|
||||||
--bin'[Compile an executable crate (default)]'
|
|
||||||
-c'[Compile and assemble, but do not link]'
|
-c'[Compile and assemble, but do not link]'
|
||||||
--cfg'[Configure the compilation environment]'
|
--cfg'[Configure the compilation environment]'
|
||||||
--crate-id'[Output the crate id and exit]'
|
--crate-id'[Output the crate id and exit]'
|
||||||
--crate-file-name'[Output the file(s) that would be written if compilation continued and exit]'
|
--crate-file-name'[Output the file(s) that would be written if compilation continued and exit]'
|
||||||
--crate-name'[Output the crate name and exit]'
|
--crate-name'[Output the crate name and exit]'
|
||||||
--dep-info'[Output dependency info to <filename> after compiling]'
|
--dep-info'[Output dependency info to <filename> after compiling]'
|
||||||
--dylib'[Compile a dynamic library crate]'
|
--crate-type'[Specify the type of crate to crate]'
|
||||||
--emit-llvm'[Produce an LLVM bitcode file]'
|
|
||||||
{-h,--help}'[Display this message]'
|
{-h,--help}'[Display this message]'
|
||||||
-L'[Add a directory to the library search path]'
|
-L'[Add a directory to the library search path]'
|
||||||
--lib'[Compile a library crate]'
|
|
||||||
--linker'[Program to use for linking instead of the default.]'
|
--linker'[Program to use for linking instead of the default.]'
|
||||||
--link-args'[FLAGS is a space-separated list of flags passed to the linker]'
|
--link-args'[FLAGS is a space-separated list of flags passed to the linker]'
|
||||||
--llvm-args'[A list of arguments to pass to llvm, comma separated]'
|
--llvm-args'[A list of arguments to pass to llvm, comma separated]'
|
||||||
@ -33,10 +30,7 @@ _rustc_opts_switches=(
|
|||||||
--parse-only'[Parse only; do not compile, assemble, or link]'
|
--parse-only'[Parse only; do not compile, assemble, or link]'
|
||||||
--passes'[Comma or space separated list of pass names to use]'
|
--passes'[Comma or space separated list of pass names to use]'
|
||||||
--pretty'[Pretty-print the input instead of compiling]'
|
--pretty'[Pretty-print the input instead of compiling]'
|
||||||
--rlib'[Compile a rust library crate as an rlib file]'
|
|
||||||
-S'[Compile only; do not assemble or link]'
|
|
||||||
--save-temps'[Write intermediate files (.bc, .opt.bc, .o) in addition to normal output]'
|
--save-temps'[Write intermediate files (.bc, .opt.bc, .o) in addition to normal output]'
|
||||||
--staticlib'[Compile a static library crate]'
|
|
||||||
--sysroot'[Override the system root]'
|
--sysroot'[Override the system root]'
|
||||||
--test'[Build a test harness]'
|
--test'[Build a test harness]'
|
||||||
--target'[Target triple cpu-manufacturer-kernel\[-os\] to compile]'
|
--target'[Target triple cpu-manufacturer-kernel\[-os\] to compile]'
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
use back::archive::{Archive, METADATA_FILENAME};
|
use back::archive::{Archive, METADATA_FILENAME};
|
||||||
use back::rpath;
|
use back::rpath;
|
||||||
use driver::driver::CrateTranslation;
|
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
@ -44,9 +44,8 @@ use syntax::attr;
|
|||||||
use syntax::attr::AttrMetaMethods;
|
use syntax::attr::AttrMetaMethods;
|
||||||
use syntax::crateid::CrateId;
|
use syntax::crateid::CrateId;
|
||||||
|
|
||||||
#[deriving(Clone, Eq)]
|
#[deriving(Clone, Eq, TotalOrd, TotalEq)]
|
||||||
pub enum OutputType {
|
pub enum OutputType {
|
||||||
OutputTypeNone,
|
|
||||||
OutputTypeBitcode,
|
OutputTypeBitcode,
|
||||||
OutputTypeAssembly,
|
OutputTypeAssembly,
|
||||||
OutputTypeLlvmAssembly,
|
OutputTypeLlvmAssembly,
|
||||||
@ -90,7 +89,7 @@ pub mod write {
|
|||||||
use back::link::{OutputTypeAssembly, OutputTypeBitcode};
|
use back::link::{OutputTypeAssembly, OutputTypeBitcode};
|
||||||
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
|
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
|
||||||
use back::link::{OutputTypeObject};
|
use back::link::{OutputTypeObject};
|
||||||
use driver::driver::CrateTranslation;
|
use driver::driver::{CrateTranslation, OutputFilenames};
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
@ -101,7 +100,6 @@ pub mod write {
|
|||||||
|
|
||||||
use std::c_str::ToCStr;
|
use std::c_str::ToCStr;
|
||||||
use std::libc::{c_uint, c_int};
|
use std::libc::{c_uint, c_int};
|
||||||
use std::path::Path;
|
|
||||||
use std::run;
|
use std::run;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
@ -125,8 +123,8 @@ pub mod write {
|
|||||||
|
|
||||||
pub fn run_passes(sess: Session,
|
pub fn run_passes(sess: Session,
|
||||||
trans: &CrateTranslation,
|
trans: &CrateTranslation,
|
||||||
output_type: OutputType,
|
output_types: &[OutputType],
|
||||||
output: &Path) {
|
output: &OutputFilenames) {
|
||||||
let llmod = trans.module;
|
let llmod = trans.module;
|
||||||
let llcx = trans.context;
|
let llcx = trans.context;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -209,10 +207,11 @@ pub mod write {
|
|||||||
// Emit the bytecode if we're either saving our temporaries or
|
// Emit the bytecode if we're either saving our temporaries or
|
||||||
// emitting an rlib. Whenever an rlib is created, the bytecode is
|
// emitting an rlib. Whenever an rlib is created, the bytecode is
|
||||||
// inserted into the archive in order to allow LTO against it.
|
// inserted into the archive in order to allow LTO against it.
|
||||||
let outputs = sess.outputs.borrow();
|
let crate_types = sess.crate_types.borrow();
|
||||||
if sess.opts.save_temps ||
|
if sess.opts.save_temps ||
|
||||||
outputs.get().iter().any(|&o| o == session::OutputRlib) {
|
(crate_types.get().contains(&session::CrateTypeRlib) &&
|
||||||
output.with_extension("bc").with_c_str(|buf| {
|
sess.opts.output_types.contains(&OutputTypeExe)) {
|
||||||
|
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -247,52 +246,68 @@ pub mod write {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time(sess.time_passes(), "codegen passes", (), |()| {
|
let mut object_file = None;
|
||||||
match output_type {
|
let mut needs_metadata = false;
|
||||||
OutputTypeNone => {}
|
for output_type in output_types.iter() {
|
||||||
|
let path = output.path(*output_type);
|
||||||
|
match *output_type {
|
||||||
OutputTypeBitcode => {
|
OutputTypeBitcode => {
|
||||||
output.with_c_str(|buf| {
|
path.with_c_str(|buf| {
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
OutputTypeLlvmAssembly => {
|
OutputTypeLlvmAssembly => {
|
||||||
output.with_c_str(|output| {
|
path.with_c_str(|output| {
|
||||||
with_codegen(tm, llmod, |cpm| {
|
with_codegen(tm, llmod, |cpm| {
|
||||||
llvm::LLVMRustPrintModule(cpm, llmod, output);
|
llvm::LLVMRustPrintModule(cpm, llmod, output);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
OutputTypeAssembly => {
|
OutputTypeAssembly => {
|
||||||
with_codegen(tm, llmod, |cpm| {
|
|
||||||
WriteOutputFile(sess, tm, cpm, llmod, output,
|
|
||||||
lib::llvm::AssemblyFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we're not using the LLVM assembler, this function
|
// If we're not using the LLVM assembler, this function
|
||||||
// could be invoked specially with output_type_assembly,
|
// could be invoked specially with output_type_assembly,
|
||||||
// so in this case we still want the metadata object
|
// so in this case we still want the metadata object
|
||||||
// file.
|
// file.
|
||||||
if sess.opts.output_type != OutputTypeAssembly {
|
let ty = OutputTypeAssembly;
|
||||||
with_codegen(tm, trans.metadata_module, |cpm| {
|
let path = if sess.opts.output_types.contains(&ty) {
|
||||||
let out = output.with_extension("metadata.o");
|
path
|
||||||
WriteOutputFile(sess, tm, cpm,
|
} else {
|
||||||
trans.metadata_module, &out,
|
needs_metadata = true;
|
||||||
lib::llvm::ObjectFile);
|
output.temp_path(OutputTypeAssembly)
|
||||||
})
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
OutputTypeExe | OutputTypeObject => {
|
|
||||||
with_codegen(tm, llmod, |cpm| {
|
with_codegen(tm, llmod, |cpm| {
|
||||||
WriteOutputFile(sess, tm, cpm, llmod, output,
|
WriteOutputFile(sess, tm, cpm, llmod, &path,
|
||||||
|
lib::llvm::AssemblyFile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
OutputTypeObject => {
|
||||||
|
object_file = Some(path);
|
||||||
|
}
|
||||||
|
OutputTypeExe => {
|
||||||
|
object_file = Some(output.temp_path(OutputTypeObject));
|
||||||
|
needs_metadata = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time(sess.time_passes(), "codegen passes", (), |()| {
|
||||||
|
match object_file {
|
||||||
|
Some(ref path) => {
|
||||||
|
with_codegen(tm, llmod, |cpm| {
|
||||||
|
WriteOutputFile(sess, tm, cpm, llmod, path,
|
||||||
lib::llvm::ObjectFile);
|
lib::llvm::ObjectFile);
|
||||||
});
|
});
|
||||||
with_codegen(tm, trans.metadata_module, |cpm| {
|
|
||||||
let out = output.with_extension("metadata.o");
|
|
||||||
WriteOutputFile(sess, tm, cpm,
|
|
||||||
trans.metadata_module, &out,
|
|
||||||
lib::llvm::ObjectFile);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
if needs_metadata {
|
||||||
|
with_codegen(tm, trans.metadata_module, |cpm| {
|
||||||
|
let out = output.temp_path(OutputTypeObject)
|
||||||
|
.with_extension("metadata.o");
|
||||||
|
WriteOutputFile(sess, tm, cpm,
|
||||||
|
trans.metadata_module, &out,
|
||||||
|
lib::llvm::ObjectFile);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -304,8 +319,10 @@ pub mod write {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_assembler(sess: Session, assembly: &Path, object: &Path) {
|
pub fn run_assembler(sess: Session, outputs: &OutputFilenames) {
|
||||||
let cc = super::get_cc_prog(sess);
|
let cc = super::get_cc_prog(sess);
|
||||||
|
let assembly = outputs.temp_path(OutputTypeAssembly);
|
||||||
|
let object = outputs.path(OutputTypeObject);
|
||||||
|
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let args = [
|
let args = [
|
||||||
@ -480,9 +497,8 @@ pub mod write {
|
|||||||
* system linkers understand.
|
* system linkers understand.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn build_link_meta(sess: Session,
|
pub fn build_link_meta(attrs: &[ast::Attribute],
|
||||||
attrs: &[ast::Attribute],
|
output: &OutputFilenames,
|
||||||
output: &Path,
|
|
||||||
symbol_hasher: &mut Sha256)
|
symbol_hasher: &mut Sha256)
|
||||||
-> LinkMeta {
|
-> LinkMeta {
|
||||||
// This calculates CMH as defined above
|
// This calculates CMH as defined above
|
||||||
@ -493,14 +509,7 @@ pub fn build_link_meta(sess: Session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let crateid = match attr::find_crateid(attrs) {
|
let crateid = match attr::find_crateid(attrs) {
|
||||||
None => {
|
None => from_str(output.out_filestem).unwrap(),
|
||||||
let stem = session::expect(
|
|
||||||
sess,
|
|
||||||
output.filestem_str(),
|
|
||||||
|| format!("output file name '{}' doesn't appear to have a stem",
|
|
||||||
output.display()));
|
|
||||||
from_str(stem).unwrap()
|
|
||||||
}
|
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -794,20 +803,21 @@ fn remove(sess: Session, path: &Path) {
|
|||||||
/// of the requested outputs for this compilation session.
|
/// of the requested outputs for this compilation session.
|
||||||
pub fn link_binary(sess: Session,
|
pub fn link_binary(sess: Session,
|
||||||
trans: &CrateTranslation,
|
trans: &CrateTranslation,
|
||||||
obj_filename: &Path,
|
outputs: &OutputFilenames,
|
||||||
out_filename: &Path,
|
|
||||||
lm: &LinkMeta) -> ~[Path] {
|
lm: &LinkMeta) -> ~[Path] {
|
||||||
let mut out_filenames = ~[];
|
let mut out_filenames = ~[];
|
||||||
let outputs = sess.outputs.borrow();
|
let crate_types = sess.crate_types.borrow();
|
||||||
for &output in outputs.get().iter() {
|
for &crate_type in crate_types.get().iter() {
|
||||||
let out_file = link_binary_output(sess, trans, output, obj_filename,
|
let out_file = link_binary_output(sess, trans, crate_type, outputs, lm);
|
||||||
out_filename, lm);
|
|
||||||
out_filenames.push(out_file);
|
out_filenames.push(out_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the temporary object file and metadata if we aren't saving temps
|
// Remove the temporary object file and metadata if we aren't saving temps
|
||||||
if !sess.opts.save_temps {
|
if !sess.opts.save_temps {
|
||||||
remove(sess, obj_filename);
|
let obj_filename = outputs.temp_path(OutputTypeObject);
|
||||||
|
if !sess.opts.output_types.contains(&OutputTypeObject) {
|
||||||
|
remove(sess, &obj_filename);
|
||||||
|
}
|
||||||
remove(sess, &obj_filename.with_extension("metadata.o"));
|
remove(sess, &obj_filename.with_extension("metadata.o"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,14 +831,14 @@ fn is_writeable(p: &Path) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filename_for_input(sess: &Session, output: session::OutputStyle, lm: &LinkMeta,
|
pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
|
||||||
out_filename: &Path) -> Path {
|
lm: &LinkMeta, out_filename: &Path) -> Path {
|
||||||
let libname = output_lib_filename(lm);
|
let libname = output_lib_filename(lm);
|
||||||
match output {
|
match crate_type {
|
||||||
session::OutputRlib => {
|
session::CrateTypeRlib => {
|
||||||
out_filename.with_filename(format!("lib{}.rlib", libname))
|
out_filename.with_filename(format!("lib{}.rlib", libname))
|
||||||
}
|
}
|
||||||
session::OutputDylib => {
|
session::CrateTypeDylib => {
|
||||||
let (prefix, suffix) = match sess.targ_cfg.os {
|
let (prefix, suffix) = match sess.targ_cfg.os {
|
||||||
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
||||||
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
||||||
@ -838,27 +848,32 @@ pub fn filename_for_input(sess: &Session, output: session::OutputStyle, lm: &Lin
|
|||||||
};
|
};
|
||||||
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
|
||||||
}
|
}
|
||||||
session::OutputStaticlib => {
|
session::CrateTypeStaticlib => {
|
||||||
out_filename.with_filename(format!("lib{}.a", libname))
|
out_filename.with_filename(format!("lib{}.a", libname))
|
||||||
}
|
}
|
||||||
session::OutputExecutable => out_filename.clone(),
|
session::CrateTypeExecutable => out_filename.clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_binary_output(sess: Session,
|
fn link_binary_output(sess: Session,
|
||||||
trans: &CrateTranslation,
|
trans: &CrateTranslation,
|
||||||
output: session::OutputStyle,
|
crate_type: session::CrateType,
|
||||||
obj_filename: &Path,
|
outputs: &OutputFilenames,
|
||||||
out_filename: &Path,
|
|
||||||
lm: &LinkMeta) -> Path {
|
lm: &LinkMeta) -> Path {
|
||||||
let out_filename = filename_for_input(&sess, output, lm, out_filename);
|
let obj_filename = outputs.temp_path(OutputTypeObject);
|
||||||
|
let out_filename = match outputs.single_output_file {
|
||||||
|
Some(ref file) => file.clone(),
|
||||||
|
None => {
|
||||||
|
let out_filename = outputs.path(OutputTypeExe);
|
||||||
|
filename_for_input(&sess, crate_type, lm, &out_filename)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Make sure the output and obj_filename are both writeable.
|
// Make sure the output and obj_filename are both writeable.
|
||||||
// Mac, FreeBSD, and Windows system linkers check this already --
|
// Mac, FreeBSD, and Windows system linkers check this already --
|
||||||
// however, the Linux linker will happily overwrite a read-only file.
|
// however, the Linux linker will happily overwrite a read-only file.
|
||||||
// We should be consistent.
|
// We should be consistent.
|
||||||
let obj_is_writeable = is_writeable(obj_filename);
|
let obj_is_writeable = is_writeable(&obj_filename);
|
||||||
let out_is_writeable = is_writeable(&out_filename);
|
let out_is_writeable = is_writeable(&out_filename);
|
||||||
if !out_is_writeable {
|
if !out_is_writeable {
|
||||||
sess.fatal(format!("Output file {} is not writeable -- check its permissions.",
|
sess.fatal(format!("Output file {} is not writeable -- check its permissions.",
|
||||||
@ -869,18 +884,18 @@ fn link_binary_output(sess: Session,
|
|||||||
obj_filename.display()));
|
obj_filename.display()));
|
||||||
}
|
}
|
||||||
|
|
||||||
match output {
|
match crate_type {
|
||||||
session::OutputRlib => {
|
session::CrateTypeRlib => {
|
||||||
link_rlib(sess, Some(trans), obj_filename, &out_filename);
|
link_rlib(sess, Some(trans), &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::OutputStaticlib => {
|
session::CrateTypeStaticlib => {
|
||||||
link_staticlib(sess, obj_filename, &out_filename);
|
link_staticlib(sess, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::OutputExecutable => {
|
session::CrateTypeExecutable => {
|
||||||
link_natively(sess, false, obj_filename, &out_filename);
|
link_natively(sess, false, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
session::OutputDylib => {
|
session::CrateTypeDylib => {
|
||||||
link_natively(sess, true, obj_filename, &out_filename);
|
link_natively(sess, true, &obj_filename, &out_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,7 +969,8 @@ fn link_rlib(sess: Session,
|
|||||||
// into the archive.
|
// into the archive.
|
||||||
let bc = obj_filename.with_extension("bc");
|
let bc = obj_filename.with_extension("bc");
|
||||||
a.add_file(&bc, false);
|
a.add_file(&bc, false);
|
||||||
if !sess.opts.save_temps {
|
if !sess.opts.save_temps &&
|
||||||
|
!sess.opts.output_types.contains(&OutputTypeBitcode) {
|
||||||
remove(sess, &bc);
|
remove(sess, &bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@ pub fn run(sess: session::Session, llmod: ModuleRef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we actually can run LTO
|
// Make sure we actually can run LTO
|
||||||
let outputs = sess.outputs.borrow();
|
let crate_types = sess.crate_types.borrow();
|
||||||
for output in outputs.get().iter() {
|
for crate_type in crate_types.get().iter() {
|
||||||
match *output {
|
match *crate_type {
|
||||||
session::OutputExecutable | session::OutputStaticlib => {}
|
session::CrateTypeExecutable | session::CrateTypeStaticlib => {}
|
||||||
_ => {
|
_ => {
|
||||||
sess.fatal("lto can only be run for executables and \
|
sess.fatal("lto can only be run for executables and \
|
||||||
static library outputs");
|
static library outputs");
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
use back::link;
|
use back::link;
|
||||||
use back::{arm, x86, x86_64, mips};
|
use back::{arm, x86, x86_64, mips};
|
||||||
use driver::session::{Aggressive, OutputExecutable};
|
use driver::session::{Aggressive, CrateTypeExecutable};
|
||||||
use driver::session::{Session, Session_, No, Less, Default};
|
use driver::session::{Session, Session_, No, Less, Default};
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use front;
|
use front;
|
||||||
@ -182,7 +182,7 @@ pub fn phase_2_configure_and_expand(sess: Session,
|
|||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
|
|
||||||
sess.building_library.set(session::building_library(sess.opts, &crate));
|
sess.building_library.set(session::building_library(sess.opts, &crate));
|
||||||
sess.outputs.set(session::collect_outputs(&sess, crate.attrs));
|
sess.crate_types.set(session::collect_crate_types(&sess, crate.attrs));
|
||||||
|
|
||||||
time(time_passes, "gated feature checking", (), |_|
|
time(time_passes, "gated feature checking", (), |_|
|
||||||
front::feature_gate::check_crate(sess, &crate));
|
front::feature_gate::check_crate(sess, &crate));
|
||||||
@ -373,8 +373,7 @@ pub fn phase_4_translate_to_llvm(sess: Session,
|
|||||||
analysis: &CrateAnalysis,
|
analysis: &CrateAnalysis,
|
||||||
outputs: &OutputFilenames) -> CrateTranslation {
|
outputs: &OutputFilenames) -> CrateTranslation {
|
||||||
time(sess.time_passes(), "translation", crate, |crate|
|
time(sess.time_passes(), "translation", crate, |crate|
|
||||||
trans::base::trans_crate(sess, crate, analysis,
|
trans::base::trans_crate(sess, crate, analysis, outputs))
|
||||||
&outputs.obj_filename))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run LLVM itself, producing a bitcode file, assembly file or object file
|
/// Run LLVM itself, producing a bitcode file, assembly file or object file
|
||||||
@ -382,29 +381,24 @@ pub fn phase_4_translate_to_llvm(sess: Session,
|
|||||||
pub fn phase_5_run_llvm_passes(sess: Session,
|
pub fn phase_5_run_llvm_passes(sess: Session,
|
||||||
trans: &CrateTranslation,
|
trans: &CrateTranslation,
|
||||||
outputs: &OutputFilenames) {
|
outputs: &OutputFilenames) {
|
||||||
|
|
||||||
if sess.no_integrated_as() {
|
if sess.no_integrated_as() {
|
||||||
let output_type = link::OutputTypeAssembly;
|
let output_type = link::OutputTypeAssembly;
|
||||||
let asm_filename = outputs.obj_filename.with_extension("s");
|
|
||||||
|
|
||||||
time(sess.time_passes(), "LLVM passes", (), |_|
|
time(sess.time_passes(), "LLVM passes", (), |_|
|
||||||
link::write::run_passes(sess,
|
link::write::run_passes(sess, trans, [output_type], outputs));
|
||||||
trans,
|
|
||||||
output_type,
|
|
||||||
&asm_filename));
|
|
||||||
|
|
||||||
link::write::run_assembler(sess, &asm_filename, &outputs.obj_filename);
|
link::write::run_assembler(sess, outputs);
|
||||||
|
|
||||||
// Remove assembly source, unless --save-temps was specified
|
// Remove assembly source, unless --save-temps was specified
|
||||||
if !sess.opts.save_temps {
|
if !sess.opts.save_temps {
|
||||||
fs::unlink(&asm_filename).unwrap();
|
fs::unlink(&outputs.temp_path(link::OutputTypeAssembly)).unwrap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
time(sess.time_passes(), "LLVM passes", (), |_|
|
time(sess.time_passes(), "LLVM passes", (), |_|
|
||||||
link::write::run_passes(sess,
|
link::write::run_passes(sess,
|
||||||
trans,
|
trans,
|
||||||
sess.opts.output_type,
|
sess.opts.output_types,
|
||||||
&outputs.obj_filename));
|
outputs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +410,7 @@ pub fn phase_6_link_output(sess: Session,
|
|||||||
time(sess.time_passes(), "linking", (), |_|
|
time(sess.time_passes(), "linking", (), |_|
|
||||||
link::link_binary(sess,
|
link::link_binary(sess,
|
||||||
trans,
|
trans,
|
||||||
&outputs.obj_filename,
|
outputs,
|
||||||
&outputs.out_filename,
|
|
||||||
&trans.link));
|
&trans.link));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,24 +439,34 @@ pub fn stop_after_phase_2(sess: Session) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_after_phase_5(sess: Session) -> bool {
|
pub fn stop_after_phase_5(sess: Session) -> bool {
|
||||||
if sess.opts.output_type != link::OutputTypeExe {
|
if !sess.opts.output_types.iter().any(|&i| i == link::OutputTypeExe) {
|
||||||
debug!("not building executable, returning early from compile_input");
|
debug!("not building executable, returning early from compile_input");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames,
|
fn write_out_deps(sess: Session,
|
||||||
crate: &ast::Crate) -> io::IoResult<()>
|
input: &Input,
|
||||||
{
|
outputs: &OutputFilenames,
|
||||||
let lm = link::build_link_meta(sess, crate.attrs, &outputs.obj_filename,
|
crate: &ast::Crate) -> io::IoResult<()> {
|
||||||
|
let lm = link::build_link_meta(crate.attrs, outputs,
|
||||||
&mut ::util::sha2::Sha256::new());
|
&mut ::util::sha2::Sha256::new());
|
||||||
|
|
||||||
let sess_outputs = sess.outputs.borrow();
|
let mut out_filenames = ~[];
|
||||||
let out_filenames = sess_outputs.get().iter()
|
for output_type in sess.opts.output_types.iter() {
|
||||||
.map(|&output| link::filename_for_input(&sess, output, &lm,
|
let file = outputs.path(*output_type);
|
||||||
&outputs.out_filename))
|
match *output_type {
|
||||||
.to_owned_vec();
|
link::OutputTypeExe => {
|
||||||
|
let crate_types = sess.crate_types.borrow();
|
||||||
|
for output in crate_types.get().iter() {
|
||||||
|
let p = link::filename_for_input(&sess, *output, &lm, &file);
|
||||||
|
out_filenames.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => { out_filenames.push(file); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write out dependency rules to the dep-info file if requested with
|
// Write out dependency rules to the dep-info file if requested with
|
||||||
// --dep-info
|
// --dep-info
|
||||||
@ -473,12 +476,7 @@ fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames,
|
|||||||
// Use default filename: crate source filename with extension replaced
|
// Use default filename: crate source filename with extension replaced
|
||||||
// by ".d"
|
// by ".d"
|
||||||
(true, None) => match *input {
|
(true, None) => match *input {
|
||||||
FileInput(ref input_path) => {
|
FileInput(..) => outputs.with_extension("d"),
|
||||||
let filestem = input_path.filestem().expect("input file must \
|
|
||||||
have stem");
|
|
||||||
let filename = out_filenames[0].dir_path().join(filestem);
|
|
||||||
filename.with_extension("d")
|
|
||||||
},
|
|
||||||
StrInput(..) => {
|
StrInput(..) => {
|
||||||
sess.warn("can not write --dep-info without a filename \
|
sess.warn("can not write --dep-info without a filename \
|
||||||
when compiling stdin.");
|
when compiling stdin.");
|
||||||
@ -526,19 +524,19 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
|
|||||||
let outputs = build_output_filenames(input, outdir, output,
|
let outputs = build_output_filenames(input, outdir, output,
|
||||||
expanded_crate.attrs, sess);
|
expanded_crate.attrs, sess);
|
||||||
|
|
||||||
write_out_deps(sess, input, outputs, &expanded_crate).unwrap();
|
write_out_deps(sess, input, &outputs, &expanded_crate).unwrap();
|
||||||
|
|
||||||
if stop_after_phase_2(sess) { return; }
|
if stop_after_phase_2(sess) { return; }
|
||||||
|
|
||||||
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
|
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
|
||||||
if stop_after_phase_3(sess) { return; }
|
if stop_after_phase_3(sess) { return; }
|
||||||
let trans = phase_4_translate_to_llvm(sess, expanded_crate,
|
let trans = phase_4_translate_to_llvm(sess, expanded_crate,
|
||||||
&analysis, outputs);
|
&analysis, &outputs);
|
||||||
(outputs, trans)
|
(outputs, trans)
|
||||||
};
|
};
|
||||||
phase_5_run_llvm_passes(sess, &trans, outputs);
|
phase_5_run_llvm_passes(sess, &trans, &outputs);
|
||||||
if stop_after_phase_5(sess) { return; }
|
if stop_after_phase_5(sess) { return; }
|
||||||
phase_6_link_output(sess, &trans, outputs);
|
phase_6_link_output(sess, &trans, &outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IdentifiedAnnotation {
|
struct IdentifiedAnnotation {
|
||||||
@ -735,22 +733,19 @@ pub fn build_session_options(binary: ~str,
|
|||||||
matches: &getopts::Matches,
|
matches: &getopts::Matches,
|
||||||
demitter: @diagnostic::Emitter)
|
demitter: @diagnostic::Emitter)
|
||||||
-> @session::Options {
|
-> @session::Options {
|
||||||
let mut outputs = ~[];
|
let crate_types = matches.opt_strs("crate-type").flat_map(|s| {
|
||||||
if matches.opt_present("lib") {
|
s.split(',').map(|part| {
|
||||||
outputs.push(session::default_lib_output());
|
match part {
|
||||||
}
|
"lib" => session::default_lib_output(),
|
||||||
if matches.opt_present("rlib") {
|
"rlib" => session::CrateTypeRlib,
|
||||||
outputs.push(session::OutputRlib)
|
"staticlib" => session::CrateTypeStaticlib,
|
||||||
}
|
"dylib" => session::CrateTypeDylib,
|
||||||
if matches.opt_present("staticlib") {
|
"bin" => session::CrateTypeExecutable,
|
||||||
outputs.push(session::OutputStaticlib)
|
_ => early_error(demitter,
|
||||||
}
|
format!("unknown crate type: `{}`", part))
|
||||||
if matches.opt_present("dylib") {
|
}
|
||||||
outputs.push(session::OutputDylib)
|
}).collect()
|
||||||
}
|
});
|
||||||
if matches.opt_present("bin") {
|
|
||||||
outputs.push(session::OutputExecutable)
|
|
||||||
}
|
|
||||||
|
|
||||||
let parse_only = matches.opt_present("parse-only");
|
let parse_only = matches.opt_present("parse-only");
|
||||||
let no_trans = matches.opt_present("no-trans");
|
let no_trans = matches.opt_present("no-trans");
|
||||||
@ -801,19 +796,30 @@ pub fn build_session_options(binary: ~str,
|
|||||||
unsafe { llvm::LLVMSetDebug(1); }
|
unsafe { llvm::LLVMSetDebug(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_type =
|
let mut output_types = if parse_only || no_trans {
|
||||||
if parse_only || no_trans {
|
~[]
|
||||||
link::OutputTypeNone
|
} else {
|
||||||
} else if matches.opt_present("S") &&
|
matches.opt_strs("emit").flat_map(|s| {
|
||||||
matches.opt_present("emit-llvm") {
|
s.split(',').map(|part| {
|
||||||
link::OutputTypeLlvmAssembly
|
match part.as_slice() {
|
||||||
} else if matches.opt_present("S") {
|
"asm" => link::OutputTypeAssembly,
|
||||||
link::OutputTypeAssembly
|
"ir" => link::OutputTypeLlvmAssembly,
|
||||||
} else if matches.opt_present("c") {
|
"bc" => link::OutputTypeBitcode,
|
||||||
link::OutputTypeObject
|
"obj" => link::OutputTypeObject,
|
||||||
} else if matches.opt_present("emit-llvm") {
|
"link" => link::OutputTypeExe,
|
||||||
link::OutputTypeBitcode
|
_ => early_error(demitter,
|
||||||
} else { link::OutputTypeExe };
|
format!("unknown emission type: `{}`",
|
||||||
|
part))
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
output_types.sort();
|
||||||
|
output_types.dedup();
|
||||||
|
if output_types.len() == 0 {
|
||||||
|
output_types.push(link::OutputTypeExe);
|
||||||
|
}
|
||||||
|
|
||||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| @Path::new(m));
|
let sysroot_opt = matches.opt_str("sysroot").map(|m| @Path::new(m));
|
||||||
let target = matches.opt_str("target").unwrap_or(host_triple());
|
let target = matches.opt_str("target").unwrap_or(host_triple());
|
||||||
let target_cpu = matches.opt_str("target-cpu").unwrap_or(~"generic");
|
let target_cpu = matches.opt_str("target-cpu").unwrap_or(~"generic");
|
||||||
@ -886,7 +892,7 @@ pub fn build_session_options(binary: ~str,
|
|||||||
matches.opt_present("crate-file-name"));
|
matches.opt_present("crate-file-name"));
|
||||||
|
|
||||||
let sopts = @session::Options {
|
let sopts = @session::Options {
|
||||||
outputs: outputs,
|
crate_types: crate_types,
|
||||||
gc: gc,
|
gc: gc,
|
||||||
optimize: opt_level,
|
optimize: opt_level,
|
||||||
custom_passes: custom_passes,
|
custom_passes: custom_passes,
|
||||||
@ -895,7 +901,7 @@ pub fn build_session_options(binary: ~str,
|
|||||||
extra_debuginfo: extra_debuginfo,
|
extra_debuginfo: extra_debuginfo,
|
||||||
lint_opts: lint_opts,
|
lint_opts: lint_opts,
|
||||||
save_temps: save_temps,
|
save_temps: save_temps,
|
||||||
output_type: output_type,
|
output_types: output_types,
|
||||||
addl_lib_search_paths: @RefCell::new(addl_lib_search_paths),
|
addl_lib_search_paths: @RefCell::new(addl_lib_search_paths),
|
||||||
ar: ar,
|
ar: ar,
|
||||||
linker: linker,
|
linker: linker,
|
||||||
@ -972,7 +978,7 @@ pub fn build_session_(sopts: @session::Options,
|
|||||||
working_dir: os::getcwd(),
|
working_dir: os::getcwd(),
|
||||||
lints: RefCell::new(HashMap::new()),
|
lints: RefCell::new(HashMap::new()),
|
||||||
node_id: Cell::new(1),
|
node_id: Cell::new(1),
|
||||||
outputs: @RefCell::new(~[]),
|
crate_types: @RefCell::new(~[]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,20 +1000,15 @@ pub fn parse_pretty(sess: Session, name: &str) -> PpMode {
|
|||||||
// rustc command line options
|
// rustc command line options
|
||||||
pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
||||||
~[
|
~[
|
||||||
optflag("c", "", "Compile and assemble, but do not link"),
|
optflag("h", "help", "Display this message"),
|
||||||
optmulti("", "cfg", "Configure the compilation
|
optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
|
||||||
environment", "SPEC"),
|
optmulti("L", "", "Add a directory to the library search path", "PATH"),
|
||||||
optflag("", "emit-llvm",
|
optmulti("", "crate-type", "Comma separated list of types of crates for the \
|
||||||
"Produce an LLVM assembly file if used with -S option;
|
compiler to emit",
|
||||||
produce an LLVM bitcode file otherwise"),
|
"[bin|lib|rlib|dylib|staticlib]"),
|
||||||
optflag("h", "help","Display this message"),
|
optmulti("", "emit", "Comma separated list of types of output for the compiler
|
||||||
optmulti("L", "", "Add a directory to the library search path",
|
to emit",
|
||||||
"PATH"),
|
"[asm|bc|ir|obj|link]"),
|
||||||
optflag("", "bin", "Compile an executable crate (default)"),
|
|
||||||
optflag("", "lib", "Compile a rust library crate using the compiler's default"),
|
|
||||||
optflag("", "rlib", "Compile a rust library crate as an rlib file"),
|
|
||||||
optflag("", "staticlib", "Compile a static library crate"),
|
|
||||||
optflag("", "dylib", "Compile a dynamic library crate"),
|
|
||||||
optopt("", "linker", "Program to use for linking instead of the default.", "LINKER"),
|
optopt("", "linker", "Program to use for linking instead of the default.", "LINKER"),
|
||||||
optopt("", "ar", "Program to use for managing archives instead of the default.", "AR"),
|
optopt("", "ar", "Program to use for managing archives instead of the default.", "AR"),
|
||||||
optflag("", "crate-id", "Output the crate id and exit"),
|
optflag("", "crate-id", "Output the crate id and exit"),
|
||||||
@ -1045,7 +1046,6 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
|||||||
typed (crates expanded, with type annotations),
|
typed (crates expanded, with type annotations),
|
||||||
or identified (fully parenthesized,
|
or identified (fully parenthesized,
|
||||||
AST nodes and blocks with IDs)", "TYPE"),
|
AST nodes and blocks with IDs)", "TYPE"),
|
||||||
optflag("S", "", "Compile only; do not assemble or link"),
|
|
||||||
optflagopt("", "dep-info",
|
optflagopt("", "dep-info",
|
||||||
"Output dependency info to <filename> after compiling", "FILENAME"),
|
"Output dependency info to <filename> after compiling", "FILENAME"),
|
||||||
optflag("", "save-temps",
|
optflag("", "save-temps",
|
||||||
@ -1081,8 +1081,35 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputFilenames {
|
pub struct OutputFilenames {
|
||||||
out_filename: Path,
|
out_directory: Path,
|
||||||
obj_filename: Path
|
out_filestem: ~str,
|
||||||
|
single_output_file: Option<Path>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputFilenames {
|
||||||
|
pub fn path(&self, flavor: link::OutputType) -> Path {
|
||||||
|
match self.single_output_file {
|
||||||
|
Some(ref path) => return path.clone(),
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
self.temp_path(flavor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn temp_path(&self, flavor: link::OutputType) -> Path {
|
||||||
|
let base = self.out_directory.join(self.out_filestem.as_slice());
|
||||||
|
match flavor {
|
||||||
|
link::OutputTypeBitcode => base.with_extension("bc"),
|
||||||
|
link::OutputTypeAssembly => base.with_extension("s"),
|
||||||
|
link::OutputTypeLlvmAssembly => base.with_extension("ll"),
|
||||||
|
link::OutputTypeObject => base.with_extension("o"),
|
||||||
|
link::OutputTypeExe => base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_extension(&self, extension: &str) -> Path {
|
||||||
|
let stem = self.out_filestem.as_slice();
|
||||||
|
self.out_directory.join(stem).with_extension(extension)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_output_filenames(input: &Input,
|
pub fn build_output_filenames(input: &Input,
|
||||||
@ -1090,83 +1117,53 @@ pub fn build_output_filenames(input: &Input,
|
|||||||
ofile: &Option<Path>,
|
ofile: &Option<Path>,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
sess: Session)
|
sess: Session)
|
||||||
-> ~OutputFilenames {
|
-> OutputFilenames {
|
||||||
let obj_path;
|
|
||||||
let out_path;
|
|
||||||
let sopts = sess.opts;
|
|
||||||
let stop_after_codegen = sopts.output_type != link::OutputTypeExe;
|
|
||||||
|
|
||||||
let obj_suffix = match sopts.output_type {
|
|
||||||
link::OutputTypeNone => ~"none",
|
|
||||||
link::OutputTypeBitcode => ~"bc",
|
|
||||||
link::OutputTypeAssembly => ~"s",
|
|
||||||
link::OutputTypeLlvmAssembly => ~"ll",
|
|
||||||
// Object and exe output both use the '.o' extension here
|
|
||||||
link::OutputTypeObject | link::OutputTypeExe => ~"o"
|
|
||||||
};
|
|
||||||
|
|
||||||
match *ofile {
|
match *ofile {
|
||||||
None => {
|
None => {
|
||||||
// "-" as input file will cause the parser to read from stdin so we
|
// "-" as input file will cause the parser to read from stdin so we
|
||||||
// have to make up a name
|
// have to make up a name
|
||||||
// We want to toss everything after the final '.'
|
// We want to toss everything after the final '.'
|
||||||
let dirpath = match *odir {
|
let dirpath = match *odir {
|
||||||
Some(ref d) => (*d).clone(),
|
Some(ref d) => d.clone(),
|
||||||
None => match *input {
|
None => os::getcwd(),
|
||||||
StrInput(_) => os::getcwd(),
|
};
|
||||||
FileInput(ref ifile) => (*ifile).dir_path()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut stem = match *input {
|
let mut stem = match *input {
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
FileInput(ref ifile) => {
|
FileInput(ref ifile) => ifile.filestem_str().unwrap().to_str(),
|
||||||
(*ifile).filestem_str().unwrap().to_str()
|
StrInput(_) => ~"rust_out"
|
||||||
}
|
};
|
||||||
StrInput(_) => ~"rust_out"
|
|
||||||
};
|
|
||||||
|
|
||||||
// If a crateid is present, we use it as the link name
|
// If a crateid is present, we use it as the link name
|
||||||
let crateid = attr::find_crateid(attrs);
|
let crateid = attr::find_crateid(attrs);
|
||||||
match crateid {
|
match crateid {
|
||||||
None => {}
|
None => {}
|
||||||
Some(crateid) => stem = crateid.name.to_str(),
|
Some(crateid) => stem = crateid.name.to_str(),
|
||||||
}
|
}
|
||||||
|
OutputFilenames {
|
||||||
if sess.building_library.get() {
|
out_directory: dirpath,
|
||||||
out_path = dirpath.join(os::dll_filename(stem));
|
out_filestem: stem,
|
||||||
obj_path = {
|
single_output_file: None,
|
||||||
let mut p = dirpath.join(stem);
|
}
|
||||||
p.set_extension(obj_suffix);
|
|
||||||
p
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
out_path = dirpath.join(stem);
|
|
||||||
obj_path = out_path.with_extension(obj_suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(ref out_file) => {
|
|
||||||
out_path = out_file.clone();
|
|
||||||
obj_path = if stop_after_codegen {
|
|
||||||
out_file.clone()
|
|
||||||
} else {
|
|
||||||
out_file.with_extension(obj_suffix)
|
|
||||||
};
|
|
||||||
|
|
||||||
if sess.building_library.get() {
|
|
||||||
sess.warn("ignoring specified output filename for library.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if *odir != None {
|
Some(ref out_file) => {
|
||||||
sess.warn("ignoring --out-dir flag due to -o flag.");
|
let ofile = if sess.opts.output_types.len() > 1 {
|
||||||
|
sess.warn("ignoring specified output filename because multiple \
|
||||||
|
outputs were requested");
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(out_file.clone())
|
||||||
|
};
|
||||||
|
if *odir != None {
|
||||||
|
sess.warn("ignoring --out-dir flag due to -o flag.");
|
||||||
|
}
|
||||||
|
OutputFilenames {
|
||||||
|
out_directory: out_file.dir_path(),
|
||||||
|
out_filestem: out_file.filestem_str().unwrap().to_str(),
|
||||||
|
single_output_file: ofile,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~OutputFilenames {
|
|
||||||
out_filename: out_path,
|
|
||||||
obj_filename: obj_path
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
|
||||||
use back::link;
|
|
||||||
use back::target_strs;
|
use back::target_strs;
|
||||||
use back;
|
use back;
|
||||||
use driver::driver::host_triple;
|
use driver::driver::host_triple;
|
||||||
@ -139,7 +138,7 @@ pub enum OptLevel {
|
|||||||
pub struct Options {
|
pub struct Options {
|
||||||
// The crate config requested for the session, which may be combined
|
// The crate config requested for the session, which may be combined
|
||||||
// with additional crate configurations during the compile process
|
// with additional crate configurations during the compile process
|
||||||
outputs: ~[OutputStyle],
|
crate_types: ~[CrateType],
|
||||||
|
|
||||||
gc: bool,
|
gc: bool,
|
||||||
optimize: OptLevel,
|
optimize: OptLevel,
|
||||||
@ -149,7 +148,7 @@ pub struct Options {
|
|||||||
extra_debuginfo: bool,
|
extra_debuginfo: bool,
|
||||||
lint_opts: ~[(lint::Lint, lint::level)],
|
lint_opts: ~[(lint::Lint, lint::level)],
|
||||||
save_temps: bool,
|
save_temps: bool,
|
||||||
output_type: back::link::OutputType,
|
output_types: ~[back::link::OutputType],
|
||||||
// This was mutable for rustpkg, which updates search paths based on the
|
// This was mutable for rustpkg, which updates search paths based on the
|
||||||
// parsed code. It remains mutable in case its replacements wants to use
|
// parsed code. It remains mutable in case its replacements wants to use
|
||||||
// this.
|
// this.
|
||||||
@ -192,11 +191,11 @@ pub enum EntryFnType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq, Clone, TotalOrd, TotalEq)]
|
#[deriving(Eq, Clone, TotalOrd, TotalEq)]
|
||||||
pub enum OutputStyle {
|
pub enum CrateType {
|
||||||
OutputExecutable,
|
CrateTypeExecutable,
|
||||||
OutputDylib,
|
CrateTypeDylib,
|
||||||
OutputRlib,
|
CrateTypeRlib,
|
||||||
OutputStaticlib,
|
CrateTypeStaticlib,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Session_ {
|
pub struct Session_ {
|
||||||
@ -219,7 +218,7 @@ pub struct Session_ {
|
|||||||
lints: RefCell<HashMap<ast::NodeId,
|
lints: RefCell<HashMap<ast::NodeId,
|
||||||
~[(lint::Lint, codemap::Span, ~str)]>>,
|
~[(lint::Lint, codemap::Span, ~str)]>>,
|
||||||
node_id: Cell<ast::NodeId>,
|
node_id: Cell<ast::NodeId>,
|
||||||
outputs: @RefCell<~[OutputStyle]>,
|
crate_types: @RefCell<~[CrateType]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Session = @Session_;
|
pub type Session = @Session_;
|
||||||
@ -374,7 +373,7 @@ impl Session_ {
|
|||||||
/// Some reasonable defaults
|
/// Some reasonable defaults
|
||||||
pub fn basic_options() -> @Options {
|
pub fn basic_options() -> @Options {
|
||||||
@Options {
|
@Options {
|
||||||
outputs: ~[],
|
crate_types: ~[],
|
||||||
gc: false,
|
gc: false,
|
||||||
optimize: No,
|
optimize: No,
|
||||||
custom_passes: ~[],
|
custom_passes: ~[],
|
||||||
@ -383,7 +382,7 @@ pub fn basic_options() -> @Options {
|
|||||||
extra_debuginfo: false,
|
extra_debuginfo: false,
|
||||||
lint_opts: ~[],
|
lint_opts: ~[],
|
||||||
save_temps: false,
|
save_temps: false,
|
||||||
output_type: link::OutputTypeExe,
|
output_types: ~[],
|
||||||
addl_lib_search_paths: @RefCell::new(HashSet::new()),
|
addl_lib_search_paths: @RefCell::new(HashSet::new()),
|
||||||
ar: None,
|
ar: None,
|
||||||
linker: None,
|
linker: None,
|
||||||
@ -413,10 +412,10 @@ pub fn expect<T:Clone>(sess: Session, opt: Option<T>, msg: || -> ~str) -> T {
|
|||||||
|
|
||||||
pub fn building_library(options: &Options, crate: &ast::Crate) -> bool {
|
pub fn building_library(options: &Options, crate: &ast::Crate) -> bool {
|
||||||
if options.test { return false }
|
if options.test { return false }
|
||||||
for output in options.outputs.iter() {
|
for output in options.crate_types.iter() {
|
||||||
match *output {
|
match *output {
|
||||||
OutputExecutable => {}
|
CrateTypeExecutable => {}
|
||||||
OutputStaticlib | OutputDylib | OutputRlib => return true
|
CrateTypeStaticlib | CrateTypeDylib | CrateTypeRlib => return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match syntax::attr::first_attr_value_str_by_name(crate.attrs, "crate_type") {
|
match syntax::attr::first_attr_value_str_by_name(crate.attrs, "crate_type") {
|
||||||
@ -430,30 +429,30 @@ pub fn building_library(options: &Options, crate: &ast::Crate) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_lib_output() -> OutputStyle {
|
pub fn default_lib_output() -> CrateType {
|
||||||
OutputRlib
|
CrateTypeRlib
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect_outputs(session: &Session,
|
pub fn collect_crate_types(session: &Session,
|
||||||
attrs: &[ast::Attribute]) -> ~[OutputStyle] {
|
attrs: &[ast::Attribute]) -> ~[CrateType] {
|
||||||
// If we're generating a test executable, then ignore all other output
|
// If we're generating a test executable, then ignore all other output
|
||||||
// styles at all other locations
|
// styles at all other locations
|
||||||
if session.opts.test {
|
if session.opts.test {
|
||||||
return ~[OutputExecutable];
|
return ~[CrateTypeExecutable];
|
||||||
}
|
}
|
||||||
let mut base = session.opts.outputs.clone();
|
let mut base = session.opts.crate_types.clone();
|
||||||
let mut iter = attrs.iter().filter_map(|a| {
|
let mut iter = attrs.iter().filter_map(|a| {
|
||||||
if a.name().equiv(&("crate_type")) {
|
if a.name().equiv(&("crate_type")) {
|
||||||
match a.value_str() {
|
match a.value_str() {
|
||||||
Some(ref n) if n.equiv(&("rlib")) => Some(OutputRlib),
|
Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib),
|
||||||
Some(ref n) if n.equiv(&("dylib")) => Some(OutputDylib),
|
Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib),
|
||||||
Some(ref n) if n.equiv(&("lib")) => {
|
Some(ref n) if n.equiv(&("lib")) => {
|
||||||
Some(default_lib_output())
|
Some(default_lib_output())
|
||||||
}
|
}
|
||||||
Some(ref n) if n.equiv(&("staticlib")) => {
|
Some(ref n) if n.equiv(&("staticlib")) => {
|
||||||
Some(OutputStaticlib)
|
Some(CrateTypeStaticlib)
|
||||||
}
|
}
|
||||||
Some(ref n) if n.equiv(&("bin")) => Some(OutputExecutable),
|
Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable),
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
session.add_lint(lint::UnknownCrateType,
|
session.add_lint(lint::UnknownCrateType,
|
||||||
ast::CRATE_NODE_ID,
|
ast::CRATE_NODE_ID,
|
||||||
@ -473,7 +472,7 @@ pub fn collect_outputs(session: &Session,
|
|||||||
});
|
});
|
||||||
base.extend(&mut iter);
|
base.extend(&mut iter);
|
||||||
if base.len() == 0 {
|
if base.len() == 0 {
|
||||||
base.push(OutputExecutable);
|
base.push(CrateTypeExecutable);
|
||||||
}
|
}
|
||||||
base.sort();
|
base.sort();
|
||||||
base.dedup();
|
base.dedup();
|
||||||
|
@ -302,12 +302,12 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if crate_file_name {
|
if crate_file_name {
|
||||||
let lm = link::build_link_meta(sess, attrs, &t_outputs.obj_filename,
|
let lm = link::build_link_meta(attrs, &t_outputs,
|
||||||
&mut ::util::sha2::Sha256::new());
|
&mut ::util::sha2::Sha256::new());
|
||||||
let outputs = session::collect_outputs(&sess, attrs);
|
let crate_types = session::collect_crate_types(&sess, attrs);
|
||||||
for &style in outputs.iter() {
|
for &style in crate_types.iter() {
|
||||||
let fname = link::filename_for_input(&sess, style, &lm,
|
let fname = link::filename_for_input(&sess, style, &lm,
|
||||||
&t_outputs.out_filename);
|
&t_outputs.with_extension(""));
|
||||||
println!("{}", fname.filename_display());
|
println!("{}", fname.filename_display());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ use back::link::{mangle_exported_name};
|
|||||||
use back::{link, abi};
|
use back::{link, abi};
|
||||||
use driver::session;
|
use driver::session;
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
|
use driver::driver::OutputFilenames;
|
||||||
use driver::driver::{CrateAnalysis, CrateTranslation};
|
use driver::driver::{CrateAnalysis, CrateTranslation};
|
||||||
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
|
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
|
||||||
use lib::llvm::{llvm, True, Vector};
|
use lib::llvm::{llvm, True, Vector};
|
||||||
@ -2657,7 +2658,7 @@ pub fn write_metadata(cx: &CrateContext, crate: &ast::Crate) -> ~[u8] {
|
|||||||
pub fn trans_crate(sess: session::Session,
|
pub fn trans_crate(sess: session::Session,
|
||||||
crate: ast::Crate,
|
crate: ast::Crate,
|
||||||
analysis: &CrateAnalysis,
|
analysis: &CrateAnalysis,
|
||||||
output: &Path) -> CrateTranslation {
|
output: &OutputFilenames) -> CrateTranslation {
|
||||||
// Before we touch LLVM, make sure that multithreading is enabled.
|
// Before we touch LLVM, make sure that multithreading is enabled.
|
||||||
unsafe {
|
unsafe {
|
||||||
use sync::one::{Once, ONCE_INIT};
|
use sync::one::{Once, ONCE_INIT};
|
||||||
@ -2677,7 +2678,7 @@ pub fn trans_crate(sess: session::Session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut symbol_hasher = Sha256::new();
|
let mut symbol_hasher = Sha256::new();
|
||||||
let link_meta = link::build_link_meta(sess, crate.attrs, output,
|
let link_meta = link::build_link_meta(crate.attrs, output,
|
||||||
&mut symbol_hasher);
|
&mut symbol_hasher);
|
||||||
|
|
||||||
// Append ".rs" to crate name as LLVM module identifier.
|
// Append ".rs" to crate name as LLVM module identifier.
|
||||||
|
@ -55,7 +55,7 @@ fn get_ast_and_resolve(cpath: &Path,
|
|||||||
binary: ~"rustdoc",
|
binary: ~"rustdoc",
|
||||||
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: @RefCell::new(libs),
|
addl_lib_search_paths: @RefCell::new(libs),
|
||||||
outputs: ~[driver::session::OutputDylib],
|
crate_types: ~[driver::session::CrateTypeDylib],
|
||||||
.. (*rustc::driver::session::basic_options()).clone()
|
.. (*rustc::driver::session::basic_options()).clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ use std::str;
|
|||||||
use extra::tempfile::TempDir;
|
use extra::tempfile::TempDir;
|
||||||
use extra::getopts;
|
use extra::getopts;
|
||||||
use extra::test;
|
use extra::test;
|
||||||
|
use rustc::back::link;
|
||||||
use rustc::driver::driver;
|
use rustc::driver::driver;
|
||||||
use rustc::driver::session;
|
use rustc::driver::session;
|
||||||
use rustc::metadata::creader::Loader;
|
use rustc::metadata::creader::Loader;
|
||||||
@ -43,7 +44,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
|
|||||||
binary: ~"rustdoc",
|
binary: ~"rustdoc",
|
||||||
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: libs,
|
addl_lib_search_paths: libs,
|
||||||
outputs: ~[session::OutputDylib],
|
crate_types: ~[session::CrateTypeDylib],
|
||||||
.. (*session::basic_options()).clone()
|
.. (*session::basic_options()).clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,8 +105,9 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>) {
|
|||||||
binary: ~"rustdoctest",
|
binary: ~"rustdoctest",
|
||||||
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
|
||||||
addl_lib_search_paths: @RefCell::new(libs),
|
addl_lib_search_paths: @RefCell::new(libs),
|
||||||
outputs: ~[session::OutputExecutable],
|
crate_types: ~[session::CrateTypeExecutable],
|
||||||
debugging_opts: session::PREFER_DYNAMIC,
|
debugging_opts: session::PREFER_DYNAMIC,
|
||||||
|
output_types: ~[link::OutputTypeExe],
|
||||||
.. (*session::basic_options()).clone()
|
.. (*session::basic_options()).clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ all:
|
|||||||
[ `$(RUSTC) --crate-id crate.rs` = "foo#0.10-pre" ]
|
[ `$(RUSTC) --crate-id crate.rs` = "foo#0.10-pre" ]
|
||||||
[ `$(RUSTC) --crate-name crate.rs` = "foo" ]
|
[ `$(RUSTC) --crate-name crate.rs` = "foo" ]
|
||||||
[ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
|
[ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
|
||||||
[ `$(RUSTC) --crate-file-name --lib --test crate.rs` = "foo" ]
|
[ `$(RUSTC) --crate-file-name --crate-type=lib --test crate.rs` = "foo" ]
|
||||||
[ `$(RUSTC) --crate-file-name --test lib.rs` = "mylib" ]
|
[ `$(RUSTC) --crate-file-name --test lib.rs` = "mylib" ]
|
||||||
$(RUSTC) --crate-file-name lib.rs
|
$(RUSTC) --crate-file-name lib.rs
|
||||||
$(RUSTC) --crate-file-name rlib.rs
|
$(RUSTC) --crate-file-name rlib.rs
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --lib lib.rs
|
$(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs
|
||||||
sleep 1
|
sleep 1
|
||||||
touch foo.rs
|
touch foo.rs
|
||||||
-rm -f $(TMPDIR)/done
|
-rm -f $(TMPDIR)/done
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
LIB := $(shell $(RUSTC) --crate-file-name --lib lib.rs)
|
LIB := $(shell $(RUSTC) --crate-file-name --crate-type=lib lib.rs)
|
||||||
|
|
||||||
$(TMPDIR)/$(LIB):
|
$(TMPDIR)/$(LIB):
|
||||||
$(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --lib lib.rs
|
$(RUSTC) --dep-info $(TMPDIR)/custom-deps-file.d --crate-type=lib lib.rs
|
||||||
touch $(TMPDIR)/done
|
touch $(TMPDIR)/done
|
||||||
|
|
||||||
-include $(TMPDIR)/custom-deps-file.d
|
-include $(TMPDIR)/custom-deps-file.d
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) --dep-info --lib lib.rs
|
$(RUSTC) --dep-info --crate-type=lib lib.rs
|
||||||
sleep 1
|
sleep 1
|
||||||
touch foo.rs
|
touch foo.rs
|
||||||
-rm -f $(TMPDIR)/done
|
-rm -f $(TMPDIR)/done
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
LIB := $(shell $(RUSTC) --crate-file-name --lib lib.rs)
|
LIB := $(shell $(RUSTC) --crate-file-name --crate-type=lib lib.rs)
|
||||||
|
|
||||||
$(TMPDIR)/$(LIB):
|
$(TMPDIR)/$(LIB):
|
||||||
$(RUSTC) --dep-info --lib lib.rs
|
$(RUSTC) --dep-info --crate-type=lib lib.rs
|
||||||
touch $(TMPDIR)/done
|
touch $(TMPDIR)/done
|
||||||
|
|
||||||
-include $(TMPDIR)/lib.d
|
-include $(TMPDIR)/foo.d
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
include ../tools.mk
|
include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) --rlib foo.rs
|
$(RUSTC) --crate-type=rlib foo.rs
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
all:
|
all:
|
||||||
$(RUSTC) rlib.rs
|
$(RUSTC) rlib.rs
|
||||||
$(RUSTC) dylib.rs && exit 1 || exit 0
|
$(RUSTC) dylib.rs && exit 1 || exit 0
|
||||||
$(RUSTC) rlib.rs --dylib
|
$(RUSTC) rlib.rs --crate-type=dylib
|
||||||
$(RUSTC) dylib.rs
|
$(RUSTC) dylib.rs
|
||||||
rm $(call DYLIB,rlib-*)
|
rm $(call DYLIB,rlib-*)
|
||||||
$(RUSTC) prog.rs && exit 1 || exit 0
|
$(RUSTC) prog.rs && exit 1 || exit 0
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) --rlib --test foo.rs
|
$(RUSTC) --crate-type=rlib --test foo.rs
|
||||||
rm $(TMPDIR)/foo.bc && exit 1 || exit 0
|
rm $(TMPDIR)/foo.bc && exit 1 || exit 0
|
||||||
|
42
src/test/run-make/output-type-permutations/Makefile
Normal file
42
src/test/run-make/output-type-permutations/Makefile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
-include ../tools.mk
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib
|
||||||
|
rm $(TMPDIR)/$(call RLIB_GLOB,bar)
|
||||||
|
rm $(TMPDIR)/$(call DYLIB_GLOB,bar)
|
||||||
|
rm $(TMPDIR)/$(call STATICLIB_GLOB,bar)
|
||||||
|
$(RUSTC) foo.rs --crate-type=bin
|
||||||
|
rm $(TMPDIR)/bar
|
||||||
|
$(RUSTC) foo.rs --emit=asm,ir,bc,obj,link
|
||||||
|
rm $(TMPDIR)/bar.ll
|
||||||
|
rm $(TMPDIR)/bar.bc
|
||||||
|
rm $(TMPDIR)/bar.s
|
||||||
|
rm $(TMPDIR)/bar.o
|
||||||
|
rm $(TMPDIR)/bar
|
||||||
|
$(RUSTC) foo.rs --emit=asm,ir,bc,obj,link --crate-type=staticlib
|
||||||
|
rm $(TMPDIR)/bar.ll
|
||||||
|
rm $(TMPDIR)/bar.bc
|
||||||
|
rm $(TMPDIR)/bar.s
|
||||||
|
rm $(TMPDIR)/bar.o
|
||||||
|
rm $(TMPDIR)/$(call STATICLIB_GLOB,bar)
|
||||||
|
$(RUSTC) foo.rs --emit=asm -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --emit=bc -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --emit=ir -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --emit=obj -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --emit=link -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/foo
|
||||||
|
rm $(TMPDIR)/foo
|
||||||
|
$(RUSTC) foo.rs --emit=bc,link --crate-type=rlib
|
||||||
|
rm $(TMPDIR)/bar.bc
|
||||||
|
rm $(TMPDIR)/$(call RLIB_GLOB,bar)
|
3
src/test/run-make/output-type-permutations/foo.rs
Normal file
3
src/test/run-make/output-type-permutations/foo.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#[crate_id = "bar"];
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,7 +1,7 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) bar.rs --dylib --rlib
|
$(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib
|
||||||
$(RUSTC) foo.rs -Z prefer-dynamic
|
$(RUSTC) foo.rs -Z prefer-dynamic
|
||||||
$(call RUN,foo)
|
$(call RUN,foo)
|
||||||
rm $(TMPDIR)/*bar*
|
rm $(TMPDIR)/*bar*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(RUSTC) bar.rs --dylib --rlib
|
$(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib
|
||||||
ls $(TMPDIR)/$(call RLIB_GLOB,bar)
|
ls $(TMPDIR)/$(call RLIB_GLOB,bar)
|
||||||
$(RUSTC) foo.rs
|
$(RUSTC) foo.rs
|
||||||
rm $(TMPDIR)/*bar*
|
rm $(TMPDIR)/*bar*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
all:
|
all:
|
||||||
$(RUSTC) bar.rs --dylib
|
$(RUSTC) bar.rs --crate-type=dylib
|
||||||
$(RUSTC) foo.rs
|
$(RUSTC) foo.rs
|
||||||
$(call RUN,foo)
|
$(call RUN,foo)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-include ../tools.mk
|
-include ../tools.mk
|
||||||
all:
|
all:
|
||||||
$(RUSTC) bar.rs --rlib
|
$(RUSTC) bar.rs --crate-type=rlib
|
||||||
$(RUSTC) foo.rs
|
$(RUSTC) foo.rs
|
||||||
$(call RUN,foo)
|
$(call RUN,foo)
|
||||||
|
@ -5,6 +5,6 @@ all:
|
|||||||
$(RUSTC) main.rs
|
$(RUSTC) main.rs
|
||||||
$(call RUN,main)
|
$(call RUN,main)
|
||||||
# ... and the loads/stores must not be optimized out.
|
# ... and the loads/stores must not be optimized out.
|
||||||
$(RUSTC) main.rs --emit-llvm -S
|
$(RUSTC) main.rs --emit=ir
|
||||||
grep "load volatile" $(TMPDIR)/main.ll
|
grep "load volatile" $(TMPDIR)/main.ll
|
||||||
grep "store volatile" $(TMPDIR)/main.ll
|
grep "store volatile" $(TMPDIR)/main.ll
|
||||||
|
Loading…
Reference in New Issue
Block a user