run_make_support/external_deps/
c_build.rs

1use std::path::PathBuf;
2
3use crate::artifact_names::{dynamic_lib_name, static_lib_name};
4use crate::external_deps::c_cxx_compiler::{cc, cxx};
5use crate::external_deps::llvm::llvm_ar;
6use crate::path_helpers::path;
7use crate::targets::{is_darwin, is_msvc, is_windows};
8
9// FIXME(Oneirical): These native build functions should take a Path-based generic.
10
11/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
12/// Built from a C file.
13#[track_caller]
14pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
15    build_native_static_lib_internal(lib_name, false)
16}
17
18/// Builds an optimized static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
19/// Built from a C file.
20#[track_caller]
21pub fn build_native_static_lib_optimized(lib_name: &str) -> PathBuf {
22    build_native_static_lib_internal(lib_name, true)
23}
24
25#[track_caller]
26fn build_native_static_lib_internal(lib_name: &str, optimzed: bool) -> PathBuf {
27    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
28    let src = format!("{lib_name}.c");
29    let lib_path = static_lib_name(lib_name);
30
31    let mut cc = cc();
32    if !is_msvc() {
33        cc.arg("-v");
34    }
35    if optimzed {
36        cc.optimize();
37    }
38    cc.arg("-c").out_exe(&obj_file).input(src).optimize().run();
39
40    let obj_file = if is_msvc() {
41        PathBuf::from(format!("{lib_name}.obj"))
42    } else {
43        PathBuf::from(format!("{lib_name}.o"))
44    };
45    llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
46    path(lib_path)
47}
48
49/// Builds a dynamic lib. The filename is computed in a target-dependent manner, relying on
50/// [`std::env::consts::DLL_PREFIX`] and [`std::env::consts::DLL_EXTENSION`].
51#[track_caller]
52pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf {
53    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
54    let src = format!("{lib_name}.c");
55    let lib_path = dynamic_lib_name(lib_name);
56    if is_msvc() {
57        cc().arg("-c").out_exe(&obj_file).input(src).run();
58    } else {
59        cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
60    };
61    let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") };
62    if is_msvc() {
63        let out_arg = format!("-out:{lib_path}");
64        cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run();
65    } else if is_darwin() {
66        cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run();
67    } else if is_windows() {
68        cc().out_exe(&lib_path)
69            .input(&obj_file)
70            .args(&["-shared", &format!("-Wl,--out-implib={lib_path}.a")])
71            .run();
72    } else {
73        cc().out_exe(&lib_path).input(&obj_file).arg("-shared").run();
74    }
75    path(lib_path)
76}
77
78/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
79/// Built from a C++ file.
80#[track_caller]
81pub fn build_native_static_lib_cxx(lib_name: &str) -> PathBuf {
82    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
83    let src = format!("{lib_name}.cpp");
84    let lib_path = static_lib_name(lib_name);
85    if is_msvc() {
86        cxx().arg("-EHs").arg("-c").out_exe(&obj_file).input(src).run();
87    } else {
88        cxx().arg("-c").out_exe(&obj_file).input(src).run();
89    };
90    let obj_file = if is_msvc() {
91        PathBuf::from(format!("{lib_name}.obj"))
92    } else {
93        PathBuf::from(format!("{lib_name}.o"))
94    };
95    llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
96    path(lib_path)
97}