Skip to content

Commit 000f0b1

Browse files
committed
Add cpp_rule_preprocessor main
1 parent dcadd7c commit 000f0b1

4 files changed

Lines changed: 157 additions & 51 deletions

File tree

cpp2rust/cpp2rust.cpp

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,16 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4-
#include <algorithm>
5-
#include <array>
4+
#include <llvm/Support/CommandLine.h>
5+
66
#include <cstdlib>
77
#include <filesystem>
88
#include <fstream>
99
#include <vector>
10-
#if defined(_WIN32)
11-
#include <windows.h>
12-
#elif defined(__linux__)
13-
#include <limits.h>
14-
#include <unistd.h>
15-
#elif defined(__APPLE__)
16-
#include <mach-o/dyld.h>
17-
#endif
18-
19-
#include <llvm/Support/CommandLine.h>
2010

2111
#include "cpp2rust_lib.h"
2212
#include "logging.h"
13+
#include "rules_dir.h"
2314

2415
namespace fs = std::filesystem;
2516

@@ -65,42 +56,6 @@ llvm::cl::list<std::string> CXXFlags("cxxflags",
6556

6657
} // namespace
6758

68-
// Get the directory of the running executable
69-
static fs::path GetExecutableDir() {
70-
#if defined(_WIN32)
71-
char path[MAX_PATH];
72-
GetModuleFileNameA(NULL, path, MAX_PATH);
73-
return fs::path(path).parent_path();
74-
#elif defined(__linux__)
75-
char path[PATH_MAX];
76-
ssize_t count = readlink("/proc/self/exe", path, PATH_MAX);
77-
return fs::path(std::string_view(path, std::max((ssize_t)0, count)))
78-
.parent_path();
79-
#elif defined(__APPLE__)
80-
uint32_t size = 0;
81-
_NSGetExecutablePath(nullptr, &size); // get path length
82-
std::vector<char> buffer(size);
83-
_NSGetExecutablePath(buffer.data(), &size);
84-
return fs::path(buffer.data()).parent_path();
85-
#endif
86-
return ".";
87-
}
88-
89-
static bool ResolveRulesDir() {
90-
std::array<fs::path, 3> candidates = {fs::path("./rules"),
91-
fs::path("../rules"),
92-
GetExecutableDir() / "../../rules"};
93-
94-
for (const auto &dir : candidates) {
95-
if (fs::exists(dir) && fs::is_directory(dir)) {
96-
RulesDir = fs::canonical(dir).string();
97-
llvm::errs() << "Using rules directory: " << RulesDir << '\n';
98-
return true;
99-
}
100-
}
101-
return false;
102-
}
103-
10459
int main(int argc, char *argv[]) {
10560
llvm::cl::HideUnrelatedOptions(cpp2rust_cmdargs);
10661
llvm::cl::ParseCommandLineOptions(argc, argv);
@@ -149,9 +104,7 @@ int main(int argc, char *argv[]) {
149104

150105
std::vector<std::string_view> cxx_flags(CXXFlags.begin(), CXXFlags.end());
151106

152-
if (RulesDir.empty() && !ResolveRulesDir()) {
153-
llvm::errs() << "ERROR: rules directory not found. "
154-
"Please specify one with --rules\n";
107+
if (RulesDir.empty() && !cpp2rust::ResolveRulesDir(RulesDir)) {
155108
return EXIT_FAILURE;
156109
}
157110

cpp2rust/cpp_rule_preprocessor.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include <llvm/Support/CommandLine.h>
5+
#include <llvm/Support/FormatVariadic.h>
6+
#include <llvm/Support/JSON.h>
7+
#include <llvm/Support/raw_ostream.h>
8+
9+
#include <cstdlib>
10+
#include <filesystem>
11+
#include <map>
12+
#include <string>
13+
14+
#include "converter/rule_src_parser.h"
15+
#include "rules_dir.h"
16+
17+
namespace fs = std::filesystem;
18+
19+
namespace {
20+
llvm::cl::OptionCategory cat("cpp-rule-preprocessor options");
21+
22+
llvm::cl::opt<std::string>
23+
RulesDir("rules",
24+
llvm::cl::desc("Directory containing rule packages (each with a "
25+
"src.cpp); ir_src.json is written next to each. "
26+
"If omitted, auto-detected as in cpp2rust"),
27+
llvm::cl::value_desc("dir"), llvm::cl::cat(cat));
28+
} // namespace
29+
30+
static void process(const fs::path &src) {
31+
llvm::errs() << "Preprocessing " << src.string() << '\n';
32+
auto strings = cpp2rust::RuleSrcParser::Extract(src);
33+
34+
// Sort by name for deterministic output.
35+
std::map<std::string, std::string> sorted;
36+
for (auto &[k, v] : strings.functions) {
37+
sorted.emplace(k, v);
38+
}
39+
for (auto &[k, v] : strings.types) {
40+
sorted.emplace(k, v);
41+
}
42+
43+
llvm::json::Object root;
44+
for (auto &[k, v] : sorted) {
45+
llvm::json::Object entry;
46+
entry["to_string"] = v;
47+
root.try_emplace(k, std::move(entry));
48+
}
49+
50+
auto out_path = src.parent_path() / "ir_src.json";
51+
std::error_code ec;
52+
llvm::raw_fd_ostream out(out_path.string(), ec);
53+
if (ec) {
54+
llvm::errs() << "ERROR: failed to open " << out_path.string() << ": "
55+
<< ec.message() << '\n';
56+
std::exit(EXIT_FAILURE);
57+
}
58+
out << llvm::formatv("{0:2}", llvm::json::Value(std::move(root))) << '\n';
59+
}
60+
61+
int main(int argc, char *argv[]) {
62+
llvm::cl::HideUnrelatedOptions(cat);
63+
llvm::cl::ParseCommandLineOptions(argc, argv);
64+
65+
if (RulesDir.empty() && !cpp2rust::ResolveRulesDir(RulesDir)) {
66+
return EXIT_FAILURE;
67+
}
68+
69+
for (const auto &entry :
70+
fs::recursive_directory_iterator(RulesDir.getValue())) {
71+
if (entry.is_regular_file() && entry.path().filename() == "src.cpp") {
72+
process(entry.path());
73+
}
74+
}
75+
return EXIT_SUCCESS;
76+
}

cpp2rust/rules_dir.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
#include "rules_dir.h"
5+
6+
#include <algorithm>
7+
#include <array>
8+
#include <filesystem>
9+
#include <string>
10+
#include <string_view>
11+
#include <vector>
12+
13+
#include <llvm/Support/raw_ostream.h>
14+
15+
#if defined(_WIN32)
16+
#include <windows.h>
17+
#elif defined(__linux__)
18+
#include <limits.h>
19+
#include <unistd.h>
20+
#elif defined(__APPLE__)
21+
#include <mach-o/dyld.h>
22+
#endif
23+
24+
namespace cpp2rust {
25+
26+
namespace fs = std::filesystem;
27+
28+
static fs::path GetExecutableDir() {
29+
#if defined(_WIN32)
30+
char path[MAX_PATH];
31+
GetModuleFileNameA(NULL, path, MAX_PATH);
32+
return fs::path(path).parent_path();
33+
#elif defined(__linux__)
34+
char path[PATH_MAX];
35+
ssize_t count = readlink("/proc/self/exe", path, PATH_MAX);
36+
return fs::path(std::string_view(path, std::max((ssize_t)0, count)))
37+
.parent_path();
38+
#elif defined(__APPLE__)
39+
uint32_t size = 0;
40+
_NSGetExecutablePath(nullptr, &size);
41+
std::vector<char> buffer(size);
42+
_NSGetExecutablePath(buffer.data(), &size);
43+
return fs::path(buffer.data()).parent_path();
44+
#endif
45+
return ".";
46+
}
47+
48+
bool ResolveRulesDir(std::string &out) {
49+
std::array<fs::path, 3> candidates = {fs::path("./rules"),
50+
fs::path("../rules"),
51+
GetExecutableDir() / "../../rules"};
52+
53+
for (const auto &dir : candidates) {
54+
if (fs::exists(dir) && fs::is_directory(dir)) {
55+
out = fs::canonical(dir).string();
56+
llvm::errs() << "Using rules directory: " << out << '\n';
57+
return true;
58+
}
59+
}
60+
llvm::errs() << "ERROR: rules directory not found. "
61+
"Please specify one with --rules\n";
62+
return false;
63+
}
64+
65+
} // namespace cpp2rust

cpp2rust/rules_dir.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
// Copyright (c) 2022-present INESC-ID.
4+
// Distributed under the MIT license that can be found in the LICENSE file.
5+
6+
#include <string>
7+
8+
namespace cpp2rust {
9+
10+
bool ResolveRulesDir(std::string &out);
11+
12+
} // namespace cpp2rust

0 commit comments

Comments
 (0)