Skip to content

Commit 41c1bdc

Browse files
committed
Merge branch 'resolve'
2 parents 7708c13 + c7cf38c commit 41c1bdc

File tree

21 files changed

+142
-182
lines changed

21 files changed

+142
-182
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
22
cmake_policy(VERSION 3.12)
33

44
project(Bear
5-
VERSION 3.0.0
5+
VERSION 3.0.2
66
DESCRIPTION "Bear is a tool to generate compilation database for clang tooling."
77
LANGUAGES C CXX
88
)

source/intercept/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ if (SUPPORT_PRELOAD)
1616
endif()
1717

1818
target_include_directories(intercept_a PUBLIC source/)
19-
target_link_libraries(intercept_a PUBLIC result_a)
19+
target_link_libraries(intercept_a PUBLIC exec_a)
2020
target_link_libraries(intercept_a PUBLIC flags_a)
2121
target_link_libraries(intercept_a PUBLIC supervise_a)
2222
target_link_libraries(intercept_a PUBLIC sys_a)
2323
target_link_libraries(intercept_a PUBLIC report_a)
24+
target_link_libraries(intercept_a PUBLIC result_a)
2425
target_link_libraries(intercept_a PUBLIC spdlog::spdlog)
2526

2627
# Create an executable from the sub projects.
@@ -33,6 +34,7 @@ target_link_libraries(intercept report_a)
3334
target_link_libraries(intercept supervise_a)
3435
target_link_libraries(intercept sys_a)
3536
target_link_libraries(intercept flags_a)
37+
target_link_libraries(intercept exec_a)
3638

3739
install(TARGETS intercept
3840
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
@@ -56,6 +58,7 @@ if (ENABLE_UNIT_TESTS)
5658
test/SessionTest.cc
5759
)
5860

61+
target_link_libraries(intercept_unit_test exec_a)
5962
target_link_libraries(intercept_unit_test intercept_a)
6063
target_link_libraries(intercept_unit_test report_a)
6164
target_link_libraries(intercept_unit_test supervise_a)

source/intercept/source/collect/Application.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ namespace ic {
7575
Session::SharedPtr session_;
7676
};
7777

78-
rust::Result<Application> Application::from(const flags::Arguments& args, sys::env::Vars&& environment)
78+
rust::Result<Application> Application::from(const flags::Arguments& args, const char **envp)
7979
{
8080
auto command = Command::from(args);
81-
auto session = Session::from(args, std::move(environment));
81+
auto session = Session::from(args, envp);
8282
auto reporter = session
8383
.and_then<Reporter::SharedPtr>([&args](const auto& session) {
8484
return Reporter::from(args, *session);

source/intercept/source/collect/Application.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ namespace ic {
3838
static constexpr char FORCE_WRAPPER[] = "--force-wrapper";
3939
static constexpr char FORCE_PRELOAD[] = "--force-preload";
4040

41-
static ::rust::Result<Application> from(const flags::Arguments& args, sys::env::Vars &&environment);
41+
static ::rust::Result<Application> from(const flags::Arguments& args, const char **envp);
4242

4343
::rust::Result<int> operator()() const;
4444

source/intercept/source/collect/Session.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@
2929

3030
namespace ic {
3131

32-
rust::Result<Session::SharedPtr> Session::from(const flags::Arguments& args, sys::env::Vars&& environment)
32+
rust::Result<Session::SharedPtr> Session::from(const flags::Arguments& args, const char **envp)
3333
#ifdef SUPPORT_PRELOAD
3434
{
3535
if (args.as_bool(ic::Application::FORCE_WRAPPER).unwrap_or(false))
36-
return WrapperSession::from(args, std::move(environment));
36+
return WrapperSession::from(args, envp);
3737
if (args.as_bool(ic::Application::FORCE_PRELOAD).unwrap_or(false))
38-
return LibraryPreloadSession::from(args, std::move(environment));
38+
return LibraryPreloadSession::from(args, envp);
3939

40-
return LibraryPreloadSession::from(args, std::move(environment));
40+
return LibraryPreloadSession::from(args, envp);
4141
}
4242
#else
4343
{

source/intercept/source/collect/Session.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace ic {
3434
class Session {
3535
public:
3636
using SharedPtr = std::shared_ptr<Session>;
37-
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, sys::env::Vars&&);
37+
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, const char **envp);
3838

3939
public:
4040
virtual ~Session() = default;

source/intercept/source/collect/SessionLibrary.cc

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
#include "collect/SessionLibrary.h"
2121

2222
#include "collect/Application.h"
23+
#include "libsys/Errors.h"
2324
#include "libsys/Path.h"
2425
#include "libsys/Process.h"
2526
#include "report/libexec/Environments.h"
27+
#include "report/libexec/Resolver.h"
2628
#include "report/supervisor/Flags.h"
2729

2830
#include <spdlog/spdlog.h>
@@ -53,30 +55,33 @@ namespace {
5355

5456
namespace ic {
5557

56-
rust::Result<Session::SharedPtr> LibraryPreloadSession::from(const flags::Arguments& args, sys::env::Vars&& environment)
58+
rust::Result<Session::SharedPtr> LibraryPreloadSession::from(const flags::Arguments& args, const char **envp)
5759
{
60+
auto verbose = args.as_bool(ic::Application::VERBOSE).unwrap_or(false);
5861
auto library = args.as_string(ic::Application::LIBRARY);
5962
auto executor = args.as_string(ic::Application::EXECUTOR);
60-
auto verbose = args.as_bool(ic::Application::VERBOSE);
63+
auto environment = sys::env::from(envp);
64+
auto path = sys::os::get_path(environment);
6165

62-
return merge(library, executor, verbose)
63-
.map<Session::SharedPtr>([&environment](auto tuple) {
64-
const auto& [library, executor, verbose] = tuple;
65-
auto result = new LibraryPreloadSession(library, executor, verbose, std::move(environment));
66-
return std::shared_ptr<Session>(result);
66+
return merge(library, executor, path)
67+
.map<Session::SharedPtr>([&verbose, &environment](auto tuple) {
68+
const auto& [library, executor, path] = tuple;
69+
return std::make_shared<LibraryPreloadSession>(library, executor, verbose, path, std::move(environment));
6770
});
6871
}
6972

7073
LibraryPreloadSession::LibraryPreloadSession(
71-
const std::string_view& library,
72-
const std::string_view& executor,
74+
const std::string_view &library,
75+
const std::string_view &executor,
7376
bool verbose,
74-
sys::env::Vars&& environment)
77+
const std::string &path,
78+
sys::env::Vars &&environment)
7579
: Session()
7680
, library_(library)
7781
, executor_(executor)
82+
, path_(path)
7883
, verbose_(verbose)
79-
, environment_(std::move(environment))
84+
, environment_(environment)
8085
{
8186
spdlog::debug("Created library preload session. [library={0}, executor={1}]", library_, executor_);
8287
}
@@ -101,18 +106,29 @@ namespace ic {
101106

102107
rust::Result<sys::Process::Builder> LibraryPreloadSession::supervise(const std::vector<std::string_view>& command) const
103108
{
109+
auto resolver = el::Resolver();
110+
auto program = resolver.from_search_path(command.front(), path_.c_str())
111+
.map<std::string>([](auto ptr) {
112+
return std::string(ptr);
113+
})
114+
.map_err<std::runtime_error>([&command](auto error) {
115+
return std::runtime_error(
116+
fmt::format("Could not found: {}: {}", command.front(), sys::error_string(error)));
117+
});
104118
auto environment = update(environment_);
105-
auto program = sys::Process::Builder(command.front())
106-
.set_environment(environment_)
107-
.resolve_executable();
108119

109120
return rust::merge(program, environment)
110121
.map<sys::Process::Builder>([&command, this](auto pair) {
111122
const auto& [program, environment] = pair;
112-
return sys::Process::Builder(executor_)
123+
auto result = sys::Process::Builder(executor_)
113124
.add_argument(executor_)
114125
.add_argument(er::flags::DESTINATION)
115-
.add_argument(server_address_)
126+
.add_argument(server_address_);
127+
if (verbose_) {
128+
result.add_argument(er::flags::VERBOSE);
129+
}
130+
131+
return result
116132
.add_argument(er::flags::EXECUTE)
117133
.add_argument(program)
118134
.add_argument(er::flags::COMMAND)

source/intercept/source/collect/SessionLibrary.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ namespace ic {
2626
class LibraryPreloadSession : public ic::Session {
2727
public:
2828
LibraryPreloadSession(
29-
const std::string_view& library,
30-
const std::string_view& executor,
31-
bool verbose,
32-
sys::env::Vars&& environment);
29+
const std::string_view &library,
30+
const std::string_view &executor,
31+
bool verbose,
32+
const std::string &path,
33+
sys::env::Vars &&environment
34+
);
3335

34-
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, sys::env::Vars&&);
36+
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, const char **envp);
3537

3638
public:
3739
[[nodiscard]] rust::Result<std::string> resolve(const std::string& name) const override;
@@ -43,6 +45,7 @@ namespace ic {
4345
private:
4446
std::string library_;
4547
std::string executor_;
48+
std::string path_;
4649
bool verbose_;
4750
sys::env::Vars environment_;
4851
};

source/intercept/source/collect/SessionWrapper.cc

Lines changed: 21 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
*/
1919

2020
#include "collect/SessionWrapper.h"
21-
2221
#include "collect/Application.h"
22+
#include "report/libexec/Resolver.h"
23+
#include "report/libexec/Environment.h"
2324
#include "report/wrapper/Environment.h"
25+
#include "libsys/Errors.h"
2426
#include "libsys/Os.h"
2527
#include "libsys/Path.h"
2628

@@ -85,31 +87,6 @@ namespace {
8587
return os;
8688
}
8789

88-
rust::Result<fs::path> is_executable(const fs::path& path)
89-
{
90-
// Check if we can get the relpath of this file
91-
std::error_code error_code;
92-
auto result = fs::canonical(path, error_code);
93-
if (error_code) {
94-
return rust::Err(std::runtime_error(error_code.message()));
95-
}
96-
// Check if the file is executable.
97-
return (0 == access(result.c_str(), X_OK))
98-
? rust::Result<fs::path>(rust::Ok(result))
99-
: rust::Result<fs::path>(rust::Err(std::runtime_error("Not executable")));
100-
}
101-
102-
rust::Result<fs::path> find_from_path(const std::list<fs::path>& paths, const fs::path& file)
103-
{
104-
for (const auto& path : paths) {
105-
auto executable = is_executable(path / file);
106-
if (executable.is_ok()) {
107-
return executable;
108-
}
109-
}
110-
return rust::Err(std::runtime_error("Not found"));
111-
}
112-
11390
rust::Result<std::list<fs::path>> list_dir(const fs::path& path)
11491
{
11592
std::list<fs::path> result;
@@ -129,42 +106,40 @@ namespace {
129106

130107
namespace ic {
131108

132-
rust::Result<Session::SharedPtr> WrapperSession::from(const flags::Arguments& args, sys::env::Vars&& environment)
109+
rust::Result<Session::SharedPtr> WrapperSession::from(const flags::Arguments& args, const char **envp)
133110
{
134111
const bool verbose = args.as_bool(ic::Application::VERBOSE).unwrap_or(false);
135-
auto path = sys::os::get_path(environment);
136112
auto wrapper_dir = args.as_string(ic::Application::WRAPPER);
137113
auto wrappers = wrapper_dir
138114
.and_then<std::list<fs::path>>([](auto wrapper_dir) {
139115
return list_dir(wrapper_dir);
140116
});
141117

142-
auto mapping_and_override = rust::merge(path, wrappers)
143-
.map<std::map<std::string, std::string>>([](auto tuple) {
144-
const auto& [paths, wrappers] = tuple;
118+
auto mapping_and_override = wrappers
119+
.map<std::map<std::string, std::string>>([&envp](auto wrappers) {
145120
// Find the executables with the same name from the path.
146-
std::map<std::string, std::string> result = {};
121+
std::map<std::string, std::string> result;
122+
el::Resolver resolver;
147123
for (const auto& wrapper : wrappers) {
148124
auto basename = wrapper.filename();
149-
auto candidate = find_from_path(paths, basename);
125+
auto candidate = resolver.from_path(basename.c_str(), const_cast<char* const*>(envp));
150126
candidate.on_success([&result, &basename](auto candidate) {
151-
result[basename] = candidate.string();
127+
result[basename] = candidate;
152128
});
153129
}
154130
return result;
155131
})
156-
.map<std::tuple<std::map<std::string, std::string>, std::map<std::string, std::string>>>([&environment](auto mapping) {
132+
.map<std::tuple<std::map<std::string, std::string>, std::map<std::string, std::string>>>([&envp](auto mapping) {
157133
std::map<std::string, std::string> override;
134+
el::Resolver resolver;
158135
// check if any environment variable is naming the real compiler
159136
for (auto implicit : IMPLICITS) {
160137
// find any of the implicit defined in environment.
161-
if (auto env_it = environment.find(implicit.env); env_it != environment.end()) {
138+
if (auto env_it = el::env::get_env_value(envp, implicit.env); env_it != nullptr) {
162139
// FIXME: it would be more correct if we shell-split the `env_it->second`
163140
// and use only the program name, but not the argument. But then how
164141
// to deal with the errors?
165-
auto program = sys::Process::Builder(env_it->second)
166-
.set_environment(environment)
167-
.resolve_executable();
142+
auto program = resolver.from_path(std::string_view(env_it), const_cast<char* const*>(envp));
168143

169144
// find the current mapping for the program the user wants to run.
170145
// and replace the program what the wrapper will call.
@@ -185,13 +160,13 @@ namespace ic {
185160
});
186161

187162
return rust::merge(wrapper_dir, mapping_and_override)
188-
.map<Session::SharedPtr>([&verbose, &environment](const auto& tuple) {
163+
.map<Session::SharedPtr>([&verbose, &envp](const auto& tuple) {
189164
const auto& [const_wrapper_dir, const_mapping_and_override] = tuple;
190165
const auto& [const_mapping, const_override] = const_mapping_and_override;
191166
std::string wrapper_dir(const_wrapper_dir);
192167
std::map<std::string, std::string> mapping(const_mapping);
193168
std::map<std::string, std::string> override(const_override);
194-
return std::make_shared<WrapperSession>(verbose, std::move(wrapper_dir), std::move(mapping), std::move(override), environment);
169+
return std::make_shared<WrapperSession>(verbose, std::move(wrapper_dir), std::move(mapping), std::move(override), sys::env::from(envp));
195170
});
196171
}
197172

@@ -200,7 +175,7 @@ namespace ic {
200175
std::string&& wrapper_dir,
201176
std::map<std::string, std::string>&& mapping,
202177
std::map<std::string, std::string>&& override,
203-
const sys::env::Vars& environment)
178+
sys::env::Vars&& environment)
204179
: Session()
205180
, verbose_(verbose)
206181
, wrapper_dir_(wrapper_dir)
@@ -250,10 +225,11 @@ namespace ic {
250225

251226
rust::Result<sys::Process::Builder> WrapperSession::supervise(const std::vector<std::string_view>& command) const
252227
{
253-
return rust::Ok(
254-
sys::Process::Builder(command.front())
228+
auto result = sys::Process::Builder(command.front())
255229
.add_arguments(command.begin(), command.end())
256-
.set_environment(set_up_environment()));
230+
.set_environment(set_up_environment());
231+
232+
return rust::Ok(result);
257233
}
258234

259235
std::string WrapperSession::get_session_type() const

source/intercept/source/collect/SessionWrapper.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ namespace ic {
3030
std::string&& wrapper_dir,
3131
std::map<std::string, std::string>&& mapping,
3232
std::map<std::string, std::string>&& override,
33-
const sys::env::Vars& environment);
33+
sys::env::Vars&& environment);
3434

35-
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, sys::env::Vars &&);
35+
static rust::Result<Session::SharedPtr> from(const flags::Arguments&, const char **envp);
3636

3737
public:
3838
[[nodiscard]] rust::Result<std::string> resolve(const std::string& name) const override;

0 commit comments

Comments
 (0)