-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule_cmdgen.cpp
More file actions
129 lines (104 loc) · 3.93 KB
/
Copy pathmodule_cmdgen.cpp
File metadata and controls
129 lines (104 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "module_cmdgen.h"
#include "cmd_line_utils.h"
#include <filesystem>
namespace fs = std::filesystem;
namespace cppm {
std::string get_ifc_path(std::string_view cmd) {
fs::path cl_path = get_command_line_argument(cmd, 0); // todo:
cl_path.remove_filename();
fs::path arch = cl_path.parent_path().filename();
return (cl_path / "../../../ifc" / arch).string();
}
std::string ModuleCommandGenerator::get_bmi_file(std::string_view output_file) {
return fs::path { output_file }.replace_extension(".ifc").string();
}
ModuleCommandGenerator::ModuleCommandGenerator(ScanItemSetView item_set, ModuleVisitor& module_visitor) :
item_set(item_set), module_visitor(module_visitor)
{
cmd_buf.reserve(16 * 1024);
}
void ModuleCommandGenerator::generate(scan_item_idx_t idx, Format format,
std::function<std::string_view(scan_item_idx_t)> bmi_file_func)
{
cmd_buf.clear();
bool is_header_unit = item_set.items[idx].is_header_unit;
bool has_export = (!module_visitor.exports[idx].empty());
bool has_import = (!module_visitor.imports_item[idx].empty());
if (!is_header_unit && !has_export && !has_import)
return;
// in all cases assume that the C++20 flag has already been set
if (format.isMSVC()) {
auto cmd_idx = item_set.items[idx].command_idx;
std::string ifcdir = get_ifc_path(item_set.commands[cmd_idx]); // todo: this is slow
fmt::format_to(cmd_buf, " /experimental:module /module:stdIfcDir \"{}\"",
ifcdir);
if (has_export)
fmt::format_to(cmd_buf, " /module:interface /module:output \"{}\"", bmi_file_func(idx));
if (is_header_unit)
fmt::format_to(cmd_buf, " /module:export /module:name fixme /module:output \"{}\"", bmi_file_func(idx));
module_visitor.visit_transitive_imports(idx, [&](scan_item_idx_t imp_idx) {
fmt::format_to(cmd_buf, " /module:reference \"{}\"", bmi_file_func(imp_idx));
});
// todo: header unit flags ?
} else if(format.isClang() || format.isClangCl()) {
if (has_import)
if(format.isClangCl())
// clang-cl doesn't support gcc compatible driver flags, it needs CC1 flags
// todo: there doesn't seem to be a CC1 equivalent of -fno-implicit-module-maps ?
fmt::format_to(cmd_buf, " -Xclang -fno-implicit-modules");
else
fmt::format_to(cmd_buf, " -fno-implicit-modules -fno-implicit-module-maps");
module_visitor.visit_transitive_imports(idx, [&](scan_item_idx_t imp_idx) {
if(!module_visitor.exports[imp_idx].empty())
fmt::format_to(cmd_buf, " -Xclang -fmodule-file={}=\"{}\"",
module_visitor.exports[imp_idx], bmi_file_func(imp_idx));
else // for header units
fmt::format_to(cmd_buf, " -Xclang -fmodule-file=\"{}\"",
bmi_file_func(imp_idx));
});
references_end = cmd_buf.size();
if (has_export)
fmt::format_to(cmd_buf, " -Xclang -emit-module-interface");
if (is_header_unit) {
std::size_t hash = std::hash<std::string_view> {} (item_set.items[idx].path);
// todo: fix the compiler so we don't need -fmodule-name or -I.
fmt::format_to(cmd_buf, " -Xclang -emit-header-module -Xclang -fmodule-name=hu_{} -I.", hash);
}
}
// todo: gcc
}
void ModuleCommandGenerator::full_cmd_to_string(std::string& str)
{
if (cmd_buf.size() > 0) {
str.resize(cmd_buf.size());
memcpy(&str[0], cmd_buf.data(), cmd_buf.size());
}
}
std::string ModuleCommandGenerator::full_cmd_to_string()
{
std::string full_cmd;
full_cmd_to_string(full_cmd);
return full_cmd;
}
void ModuleCommandGenerator::references_to_string(std::string& str)
{
if (references_end > 0) {
str.resize(references_end);
memcpy(&str[0], cmd_buf.data(), references_end);
}
}
std::string ModuleCommandGenerator::references_to_string()
{
std::string references;
references_to_string(references);
return references;
}
ModuleCommandGenerator::Format ModuleCommandGenerator::detect_format(std::string_view cmd) {
// todo:
if (cmd.find("clang-cl.exe") != std::string_view::npos)
return { ClangCl };
if (cmd.find("/Fo") != std::string_view::npos)
return { MSVC };
return { Clang };
}
} // namespace cppm