| opt_str_seq flags; | opt_str_seq flags; | ||||
| opt_str_seq c_flags; | opt_str_seq c_flags; | ||||
| opt_str_seq cxx_flags; | opt_str_seq cxx_flags; | ||||
| opt_str_seq link_flags; | |||||
| opt_str_seq c_compile_file; | opt_str_seq c_compile_file; | ||||
| opt_str_seq cxx_compile_file; | opt_str_seq cxx_compile_file; | ||||
| opt_str_seq create_archive; | opt_str_seq create_archive; | ||||
| read_argv_acc{"Flags", flags}, | read_argv_acc{"Flags", flags}, | ||||
| read_argv_acc{"C-Flags", c_flags}, | read_argv_acc{"C-Flags", c_flags}, | ||||
| read_argv_acc{"C++-Flags", cxx_flags}, | read_argv_acc{"C++-Flags", cxx_flags}, | ||||
| read_argv_acc{"Link-Flags", link_flags}, | |||||
| // Options for flags | // Options for flags | ||||
| lm::read_bool("Optimize", do_optimize), | lm::read_bool("Optimize", do_optimize), | ||||
| lm::read_bool("Debug", do_debug), | lm::read_bool("Debug", do_debug), | ||||
| bool is_gnu_like = is_gnu || is_clang; | bool is_gnu_like = is_gnu || is_clang; | ||||
| // Now convert the flags we've been given into a real toolchain | // Now convert the flags we've been given into a real toolchain | ||||
| auto get_compiler = [&](bool is_cxx) -> string { | |||||
| if (is_cxx && cxx_compiler_fpath) { | |||||
| auto get_compiler = [&](language lang) -> string { | |||||
| if (lang == language::cxx && cxx_compiler_fpath) { | |||||
| return *cxx_compiler_fpath; | return *cxx_compiler_fpath; | ||||
| } | } | ||||
| if (!is_cxx && c_compiler_fpath) { | |||||
| if (lang == language::c && c_compiler_fpath) { | |||||
| return *c_compiler_fpath; | return *c_compiler_fpath; | ||||
| } | } | ||||
| if (!compiler_id.has_value()) { | if (!compiler_id.has_value()) { | ||||
| fail(context, "Unable to determine what compiler to use."); | fail(context, "Unable to determine what compiler to use."); | ||||
| } | } | ||||
| if (is_gnu) { | if (is_gnu) { | ||||
| return is_cxx ? "g++" : "gcc"; | |||||
| return (lang == language::cxx) ? "g++" : "gcc"; | |||||
| } | } | ||||
| if (is_clang) { | if (is_clang) { | ||||
| return is_cxx ? "clang++" : "clang"; | |||||
| return (lang == language::cxx) ? "clang++" : "clang"; | |||||
| } | } | ||||
| if (is_msvc) { | if (is_msvc) { | ||||
| return "cl.exe"; | return "cl.exe"; | ||||
| return cxx_ver_iter->second; | return cxx_ver_iter->second; | ||||
| }; | }; | ||||
| auto get_flags = [&](bool is_cxx) -> string_seq { | |||||
| auto get_flags = [&](language lang) -> string_seq { | |||||
| string_seq ret; | string_seq ret; | ||||
| if (flags) { | if (flags) { | ||||
| extend(ret, *flags); | extend(ret, *flags); | ||||
| } | } | ||||
| if (is_cxx && cxx_flags) { | |||||
| if (lang == language::cxx && cxx_flags) { | |||||
| extend(ret, *cxx_flags); | extend(ret, *cxx_flags); | ||||
| } | } | ||||
| if (!is_cxx && c_flags) { | |||||
| if (lang == language::cxx && cxx_version) { | |||||
| extend(ret, get_cxx_version_flags()); | |||||
| } | |||||
| if (lang == language::c && c_flags) { | |||||
| extend(ret, *c_flags); | extend(ret, *c_flags); | ||||
| } | } | ||||
| if (!is_cxx && c_version) { | |||||
| if (lang == language::c && c_version) { | |||||
| extend(ret, get_c_version_flags()); | extend(ret, get_c_version_flags()); | ||||
| } | } | ||||
| if (is_cxx && cxx_version) { | |||||
| extend(ret, get_cxx_version_flags()); | |||||
| } | |||||
| if (is_msvc) { | if (is_msvc) { | ||||
| strv rt_lib = "/MT"; | strv rt_lib = "/MT"; | ||||
| if (do_optimize.has_value() && *do_optimize) { | if (do_optimize.has_value() && *do_optimize) { | ||||
| } | } | ||||
| ret.emplace_back(rt_lib); | ret.emplace_back(rt_lib); | ||||
| extend(ret, {"/nologo", "<FLAGS>", "/c", "<IN>", "/permissive-", "/Fo<OUT>"}); | extend(ret, {"/nologo", "<FLAGS>", "/c", "<IN>", "/permissive-", "/Fo<OUT>"}); | ||||
| if (is_cxx) { | |||||
| if (lang == language::cxx) { | |||||
| extend(ret, {"/EHsc"}); | extend(ret, {"/EHsc"}); | ||||
| } | } | ||||
| } else if (is_gnu_like) { | } else if (is_gnu_like) { | ||||
| if (compile_launcher) { | if (compile_launcher) { | ||||
| extend(c, *compile_launcher); | extend(c, *compile_launcher); | ||||
| } | } | ||||
| c.push_back(get_compiler(false)); | |||||
| extend(c, get_flags(false)); | |||||
| c.push_back(get_compiler(language::c)); | |||||
| extend(c, get_flags(language::c)); | |||||
| return c; | return c; | ||||
| }); | }); | ||||
| if (compile_launcher) { | if (compile_launcher) { | ||||
| extend(cxx, *compile_launcher); | extend(cxx, *compile_launcher); | ||||
| } | } | ||||
| cxx.push_back(get_compiler(true)); | |||||
| extend(cxx, get_flags(true)); | |||||
| cxx.push_back(get_compiler(language::cxx)); | |||||
| extend(cxx, get_flags(language::cxx)); | |||||
| return cxx; | return cxx; | ||||
| }); | }); | ||||
| if (!compiler_id) { | if (!compiler_id) { | ||||
| fail(context, "Unable to deduce how to link executables without a Compiler-ID"); | fail(context, "Unable to deduce how to link executables without a Compiler-ID"); | ||||
| } | } | ||||
| string_seq ret; | |||||
| if (is_msvc) { | if (is_msvc) { | ||||
| return {get_compiler(true), "/nologo", "/EHsc", "<IN>", "/Fe<OUT>"}; | |||||
| ret = {get_compiler(language::cxx), "/nologo", "/EHsc", "<IN>", "/Fe<OUT>"}; | |||||
| } else if (is_gnu_like) { | } else if (is_gnu_like) { | ||||
| return {get_compiler(true), | |||||
| ret = {get_compiler(language::cxx), | |||||
| "-fPIC", | "-fPIC", | ||||
| "-fdiagnostics-color", | "-fdiagnostics-color", | ||||
| "<IN>", | "<IN>", | ||||
| "-pthread", | "-pthread", | ||||
| "-lstdc++fs", | "-lstdc++fs", | ||||
| "-o<OUT>"}; | "-o<OUT>"}; | ||||
| } else { | |||||
| assert(false && "No link-exe command"); | |||||
| std::terminate(); | |||||
| } | } | ||||
| assert(false && "No link-exe command"); | |||||
| std::terminate(); | |||||
| if (link_flags) { | |||||
| extend(ret, *link_flags); | |||||
| } | |||||
| return ret; | |||||
| }); | }); | ||||
| return tc.realize(); | return tc.realize(); |