rebuild when build failed with new options; generate compile commands include linker commands
1139 lines
46 KiB
Diff
1139 lines
46 KiB
Diff
diff --git a/source/citnames/source/Output.cc b/source/citnames/source/Output.cc
|
|
index c10cbd9..67b27bb 100644
|
|
--- a/source/citnames/source/Output.cc
|
|
+++ b/source/citnames/source/Output.cc
|
|
@@ -156,6 +156,7 @@ namespace cs {
|
|
} else {
|
|
json["command"] = sh::join(rhs.arguments);
|
|
}
|
|
+ json["rebuild"] = rhs.rebuild;
|
|
|
|
return json;
|
|
}
|
|
@@ -186,6 +187,7 @@ namespace cs {
|
|
} else {
|
|
throw std::runtime_error("Field 'command' or 'arguments' not found");
|
|
}
|
|
+ j.at("rebuild").get_to(entry.rebuild);
|
|
|
|
validate(entry);
|
|
}
|
|
@@ -194,7 +196,8 @@ namespace cs {
|
|
return (lhs.file == rhs.file)
|
|
&& (lhs.directory == rhs.directory)
|
|
&& (lhs.output == rhs.output)
|
|
- && (lhs.arguments == rhs.arguments);
|
|
+ && (lhs.arguments == rhs.arguments)
|
|
+ && (lhs.rebuild == rhs.rebuild);
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &os, const Entry &entry) {
|
|
@@ -237,11 +240,9 @@ namespace cs {
|
|
size_t count = 0;
|
|
nlohmann::json json = nlohmann::json::array();
|
|
for (const auto &entry : entries) {
|
|
- if (content_filter.apply(entry) && duplicate_filter.apply(entry)) {
|
|
- auto json_entry = cs::to_json(entry, format);
|
|
- json.emplace_back(std::move(json_entry));
|
|
- ++count;
|
|
- }
|
|
+ auto json_entry = cs::to_json(entry, format);
|
|
+ json.emplace_back(std::move(json_entry));
|
|
+ ++count;
|
|
}
|
|
|
|
ostream << std::setw(2) << json << std::endl;
|
|
diff --git a/source/citnames/source/Output.h b/source/citnames/source/Output.h
|
|
index d0819ab..6c91b0c 100644
|
|
--- a/source/citnames/source/Output.h
|
|
+++ b/source/citnames/source/Output.h
|
|
@@ -49,6 +49,7 @@ namespace cs {
|
|
fs::path directory;
|
|
std::optional<fs::path> output;
|
|
std::list<std::string> arguments;
|
|
+ bool rebuild;
|
|
};
|
|
|
|
// Convenient methods for these types.
|
|
diff --git a/source/citnames/source/semantic/Semantic.cc b/source/citnames/source/semantic/Semantic.cc
|
|
index 65cb5ab..409664b 100644
|
|
--- a/source/citnames/source/semantic/Semantic.cc
|
|
+++ b/source/citnames/source/semantic/Semantic.cc
|
|
@@ -65,12 +65,14 @@ namespace cs::semantic {
|
|
fs::path compiler,
|
|
std::list<std::string> flags,
|
|
std::vector<fs::path> sources,
|
|
- std::optional<fs::path> output)
|
|
+ std::optional<fs::path> output,
|
|
+ bool rebuild)
|
|
: working_dir(std::move(working_dir))
|
|
, compiler(std::move(compiler))
|
|
, flags(std::move(flags))
|
|
, sources(std::move(sources))
|
|
, output(std::move(output))
|
|
+ , rebuild(rebuild)
|
|
{ }
|
|
|
|
bool Compile::operator==(const Semantic &rhs) const {
|
|
@@ -82,7 +84,8 @@ namespace cs::semantic {
|
|
&& (compiler == ptr->compiler)
|
|
&& (output == ptr->output)
|
|
&& (sources == ptr->sources)
|
|
- && (flags == ptr->flags);
|
|
+ && (flags == ptr->flags)
|
|
+ && (rebuild == ptr->rebuild);
|
|
}
|
|
return false;
|
|
}
|
|
@@ -93,6 +96,7 @@ namespace cs::semantic {
|
|
<< ", flags: " << fmt::format("[{}]", fmt::join(flags.begin(), flags.end(), ", "))
|
|
<< ", sources: " << fmt::format("[{}]", fmt::join(sources.begin(), sources.end(), ", "))
|
|
<< ", output: " << (output ? output.value().string() : "")
|
|
+ << ", rebuild : " << std::boolalpha << rebuild
|
|
<< " }";
|
|
return os;
|
|
}
|
|
@@ -114,18 +118,23 @@ namespace cs::semantic {
|
|
};
|
|
std::list<cs::Entry> results;
|
|
for (const auto& source : sources) {
|
|
+ bool is_linker = source == "NULL_SOURCE_FOR_LD";
|
|
cs::Entry result {
|
|
- abspath(source),
|
|
+ is_linker ? source : abspath(source),
|
|
working_dir,
|
|
output ? std::optional(abspath(output.value())) : std::nullopt,
|
|
- { compiler.string() }
|
|
+ { compiler.string() },
|
|
+ rebuild
|
|
};
|
|
std::copy(flags.begin(), flags.end(), std::back_inserter(result.arguments));
|
|
if (output) {
|
|
result.arguments.emplace_back("-o");
|
|
result.arguments.push_back(output.value().string());
|
|
}
|
|
- result.arguments.push_back(source);
|
|
+
|
|
+ if (!is_linker) {
|
|
+ result.arguments.push_back(source);
|
|
+ }
|
|
results.emplace_back(std::move(result));
|
|
}
|
|
return results;
|
|
diff --git a/source/citnames/source/semantic/Semantic.h b/source/citnames/source/semantic/Semantic.h
|
|
index 3feaa7e..ded1d2e 100644
|
|
--- a/source/citnames/source/semantic/Semantic.h
|
|
+++ b/source/citnames/source/semantic/Semantic.h
|
|
@@ -87,7 +87,8 @@ namespace cs::semantic {
|
|
fs::path compiler,
|
|
std::list<std::string> flags,
|
|
std::vector<fs::path> sources,
|
|
- std::optional<fs::path> output);
|
|
+ std::optional<fs::path> output,
|
|
+ bool rebuild);
|
|
|
|
bool operator==(Semantic const&) const override;
|
|
std::ostream& operator<<(std::ostream&) const override;
|
|
@@ -100,5 +101,6 @@ namespace cs::semantic {
|
|
std::list<std::string> flags;
|
|
std::vector<fs::path> sources;
|
|
std::optional<fs::path> output;
|
|
+ bool rebuild;
|
|
};
|
|
}
|
|
diff --git a/source/citnames/source/semantic/ToolGcc.cc b/source/citnames/source/semantic/ToolGcc.cc
|
|
index cf23ca0..35ac6d8 100644
|
|
--- a/source/citnames/source/semantic/ToolGcc.cc
|
|
+++ b/source/citnames/source/semantic/ToolGcc.cc
|
|
@@ -122,10 +122,10 @@ namespace {
|
|
output = std::make_optional(std::move(candidate));
|
|
break;
|
|
}
|
|
- case CompilerFlagType::LINKER:
|
|
case CompilerFlagType::PREPROCESSOR_MAKE:
|
|
- case CompilerFlagType::DIRECTORY_SEARCH_LINKER:
|
|
break;
|
|
+ case CompilerFlagType::DIRECTORY_SEARCH_LINKER:
|
|
+ case CompilerFlagType::LINKER:
|
|
default: {
|
|
std::copy(flag.arguments.begin(), flag.arguments.end(), std::back_inserter(arguments));
|
|
break;
|
|
@@ -242,9 +242,15 @@ namespace cs::semantic {
|
|
{"--", {MatchInstruction::PREFIX, CompilerFlagType::OTHER}},
|
|
};
|
|
|
|
+ const FlagsByName ToolGcc::FLAG_LD_DEFINITION = {
|
|
+ {"-o", {MatchInstruction::EXACTLY_WITH_1_OPT_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT}},
|
|
+ };
|
|
+
|
|
rust::Result<SemanticPtr> ToolGcc::recognize(const Execution &execution) const {
|
|
if (is_compiler_call(execution.executable)) {
|
|
return compilation(execution);
|
|
+ } else if (is_linker_call(execution.executable)) {
|
|
+ return link(execution);
|
|
}
|
|
return rust::Ok(SemanticPtr());
|
|
}
|
|
@@ -265,10 +271,30 @@ namespace cs::semantic {
|
|
return std::regex_match(program.filename().c_str(), m, pattern);
|
|
}
|
|
|
|
+ bool ToolGcc::is_linker_call(const fs::path& program) const {
|
|
+ static const auto pattern = std::regex(
|
|
+ // - ar
|
|
+ // - ld
|
|
+ // - lld
|
|
+ // - ld.bfd
|
|
+ // - ld.gold
|
|
+ // - with prefixes like: arm-none-eabi-
|
|
+ R"(^(([^-]*-)*(ar|ld|lld|ld\.bfd|ld\.gold))$)"
|
|
+ );
|
|
+
|
|
+ std::cmatch m;
|
|
+ return std::regex_match(program.filename().c_str(), m, pattern);
|
|
+ }
|
|
+
|
|
rust::Result<SemanticPtr> ToolGcc::compilation(const Execution &execution) const {
|
|
return compilation(FLAG_DEFINITION, execution);
|
|
}
|
|
|
|
+ rust::Result<SemanticPtr> ToolGcc::link(const Execution &execution) const {
|
|
+ return compilation(FLAG_LD_DEFINITION, execution);
|
|
+ }
|
|
+
|
|
+
|
|
rust::Result<SemanticPtr> ToolGcc::compilation(const FlagsByName &flags, const Execution &execution) {
|
|
const auto &parser =
|
|
Repeat(
|
|
@@ -293,12 +319,15 @@ namespace cs::semantic {
|
|
|
|
auto[arguments, sources, output] = split(flags);
|
|
// Validate: must have source files.
|
|
- if (sources.empty()) {
|
|
- return rust::Err(std::runtime_error("Source files not found for compilation."));
|
|
- }
|
|
- // TODO: introduce semantic type for linking
|
|
- if (linking(flags)) {
|
|
- arguments.insert(arguments.begin(), "-c");
|
|
+ if (ToolGcc().is_linker_call(execution.executable) && sources.empty()) {
|
|
+ sources.emplace_back("NULL_SOURCE_FOR_LD");
|
|
+ } else {
|
|
+ if (sources.empty()) {
|
|
+ return rust::Err(std::runtime_error("Source files not found for compilation."));
|
|
+ }
|
|
+ if (linking(flags)) {
|
|
+ arguments.insert(arguments.begin(), "-c");
|
|
+ }
|
|
}
|
|
|
|
SemanticPtr result = std::make_shared<Compile>(
|
|
@@ -306,7 +335,9 @@ namespace cs::semantic {
|
|
execution.executable,
|
|
std::move(arguments),
|
|
std::move(sources),
|
|
- std::move(output)
|
|
+ std::move(output),
|
|
+ execution.environment.find(cmd::wrapper::KEY_REBUILD) ==
|
|
+ execution.environment.end() ? false : true
|
|
);
|
|
return rust::Ok(std::move(result));
|
|
});
|
|
diff --git a/source/citnames/source/semantic/ToolGcc.h b/source/citnames/source/semantic/ToolGcc.h
|
|
index b8232b9..83d99e5 100644
|
|
--- a/source/citnames/source/semantic/ToolGcc.h
|
|
+++ b/source/citnames/source/semantic/ToolGcc.h
|
|
@@ -33,12 +33,19 @@ namespace cs::semantic {
|
|
[[nodiscard]]
|
|
virtual bool is_compiler_call(const fs::path& program) const;
|
|
|
|
+ [[nodiscard]]
|
|
+ virtual bool is_linker_call(const fs::path& program) const;
|
|
+
|
|
[[nodiscard]]
|
|
virtual rust::Result<SemanticPtr> compilation(const Execution &execution) const;
|
|
|
|
+ [[nodiscard]]
|
|
+ virtual rust::Result<SemanticPtr> link(const Execution &execution) const;
|
|
+
|
|
[[nodiscard]]
|
|
static rust::Result<SemanticPtr> compilation(const FlagsByName &flags, const Execution &execution);
|
|
|
|
static const FlagsByName FLAG_DEFINITION;
|
|
+ static const FlagsByName FLAG_LD_DEFINITION;
|
|
};
|
|
}
|
|
diff --git a/source/citnames/test/OutputTest.cc b/source/citnames/test/OutputTest.cc
|
|
index 0a6540a..4b596dd 100644
|
|
--- a/source/citnames/test/OutputTest.cc
|
|
+++ b/source/citnames/test/OutputTest.cc
|
|
@@ -65,9 +65,9 @@ namespace {
|
|
TEST(compilation_database, same_entries_read_back)
|
|
{
|
|
std::list<cs::Entry> expected = {
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" } },
|
|
- { "entries.c", "/path/to", { "entries.o" }, { "cc", "-c", "-o", "entries.o", "entries.c" } },
|
|
+ { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" }, false },
|
|
+ { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" }, false },
|
|
+ { "entries.c", "/path/to", { "entries.o" }, { "cc", "-c", "-o", "entries.o", "entries.c" }, false },
|
|
};
|
|
|
|
value_serialized_and_read_back(expected, expected, AS_ARGUMENTS);
|
|
@@ -77,39 +77,20 @@ namespace {
|
|
TEST(compilation_database, entries_without_output_read_back)
|
|
{
|
|
std::list<cs::Entry> input = {
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" } },
|
|
- { "entries.c", "/path/to", { "entries.o" }, { "cc", "-c", "-o", "entries.o", "entries.c" } },
|
|
+ { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" }, false },
|
|
+ { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" }, false },
|
|
+ { "entries.c", "/path/to", { "entries.o" }, { "cc", "-c", "-o", "entries.o", "entries.c" }, false },
|
|
};
|
|
std::list<cs::Entry> expected = {
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" } },
|
|
- { "entries.c", "/path/to", std::nullopt, { "cc", "-c", "-o", "entries.o", "entries.c" } },
|
|
+ { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" }, false },
|
|
+ { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" }, false },
|
|
+ { "entries.c", "/path/to", std::nullopt, { "cc", "-c", "-o", "entries.o", "entries.c" }, false },
|
|
};
|
|
|
|
value_serialized_and_read_back(input, expected, AS_ARGUMENTS_NO_OUTPUT);
|
|
value_serialized_and_read_back(input, expected, AS_COMMAND_NO_OUTPUT);
|
|
}
|
|
|
|
- TEST(compilation_database, merged_entries_read_back)
|
|
- {
|
|
- std::list<cs::Entry> input = {
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" } },
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc1", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc1", "-c", "entry_two.c" } },
|
|
- };
|
|
- std::list<cs::Entry> expected = {
|
|
- { "entry_one.c", "/path/to", std::nullopt, { "cc", "-c", "entry_one.c" } },
|
|
- { "entry_two.c", "/path/to", std::nullopt, { "cc", "-c", "entry_two.c" } },
|
|
- };
|
|
-
|
|
- value_serialized_and_read_back(input, expected, AS_ARGUMENTS);
|
|
- value_serialized_and_read_back(input, expected, AS_COMMAND);
|
|
- value_serialized_and_read_back(input, expected, AS_ARGUMENTS_NO_OUTPUT);
|
|
- value_serialized_and_read_back(input, expected, AS_COMMAND_NO_OUTPUT);
|
|
- }
|
|
-
|
|
TEST(compilation_database, deserialize_fails_with_empty_stream)
|
|
{
|
|
cs::CompilationDatabase sut(AS_COMMAND, NO_FILTER);
|
|
diff --git a/source/citnames/test/ToolClangTest.cc b/source/citnames/test/ToolClangTest.cc
|
|
index dabc695..2f5af19 100644
|
|
--- a/source/citnames/test/ToolClangTest.cc
|
|
+++ b/source/citnames/test/ToolClangTest.cc
|
|
@@ -55,7 +55,8 @@ namespace {
|
|
input.executable,
|
|
{"-c"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -65,7 +66,7 @@ namespace {
|
|
EXPECT_EQ(expected, *(result.unwrap().get()));
|
|
}
|
|
|
|
- TEST(ToolClang, linker_flag_filtered) {
|
|
+ TEST(ToolClang, linker_flag_not_filtered) {
|
|
const Execution input = {
|
|
"/usr/bin/clang",
|
|
{"clang", "-L.", "-lthing", "-o", "exe", "source.c"},
|
|
@@ -75,9 +76,10 @@ namespace {
|
|
const Compile expected(
|
|
input.working_dir,
|
|
input.executable,
|
|
- {"-c"},
|
|
+ {"-c", "-L.", "-lthing"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("exe")}
|
|
+ {fs::path("exe")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -125,7 +127,8 @@ namespace {
|
|
input.executable,
|
|
{"-c", "-Xclang", "-load", "-Xclang", "/path/to/LLVMHello.so"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -159,7 +162,8 @@ namespace {
|
|
input.executable,
|
|
{"-c", "-Xarch_arg1", "arg2", "-Xarch_device", "device1", "-Xarch_host", "host1"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -191,7 +195,8 @@ namespace {
|
|
input.executable,
|
|
{"-c", "-Xcuda-fatbinary", "arg1", "-Xcuda-ptxas", "arg2"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -223,7 +228,8 @@ namespace {
|
|
input.executable,
|
|
{"-c", "-Xopenmp-target", "arg1", "-Xopenmp-target=arg1", "arg2"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
@@ -255,7 +261,8 @@ namespace {
|
|
input.executable,
|
|
{"-c", "-Z", "arg1", "-aargs", "--analyze"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")}
|
|
+ {fs::path("source.o")},
|
|
+ false
|
|
);
|
|
|
|
ToolClang sut({});
|
|
diff --git a/source/citnames/test/ToolGccTest.cc b/source/citnames/test/ToolGccTest.cc
|
|
index 36f13ff..6b5595e 100644
|
|
--- a/source/citnames/test/ToolGccTest.cc
|
|
+++ b/source/citnames/test/ToolGccTest.cc
|
|
@@ -69,7 +69,8 @@ namespace {
|
|
input.executable,
|
|
{"-c"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("source.o")})
|
|
+ {fs::path("source.o")},
|
|
+ false)
|
|
);
|
|
|
|
ToolGcc sut({});
|
|
@@ -79,7 +80,7 @@ namespace {
|
|
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
|
|
}
|
|
|
|
- TEST(ToolGcc, linker_flag_filtered) {
|
|
+ TEST(ToolGcc, linker_flag_not_filtered) {
|
|
Execution input = {
|
|
"/usr/bin/cc",
|
|
{"cc", "-L.", "-lthing", "-o", "exe", "source.c"},
|
|
@@ -90,9 +91,10 @@ namespace {
|
|
new Compile(
|
|
input.working_dir,
|
|
input.executable,
|
|
- {"-c"},
|
|
+ {"-c", "-L.", "-lthing"},
|
|
{fs::path("source.c")},
|
|
- {fs::path("exe")}
|
|
+ {fs::path("exe")},
|
|
+ false
|
|
)
|
|
);
|
|
|
|
@@ -139,7 +141,8 @@ namespace {
|
|
"-I", "/usr/include/path3",
|
|
},
|
|
{fs::path("source.c")},
|
|
- std::nullopt
|
|
+ std::nullopt,
|
|
+ false
|
|
)
|
|
);
|
|
|
|
diff --git a/source/config.h.in b/source/config.h.in
|
|
index f421871..5f75195 100644
|
|
--- a/source/config.h.in
|
|
+++ b/source/config.h.in
|
|
@@ -122,6 +122,9 @@ namespace cmd {
|
|
|
|
constexpr char KEY_DESTINATION[] = "INTERCEPT_REPORT_DESTINATION";
|
|
constexpr char KEY_VERBOSE[] = "INTERCEPT_VERBOSE";
|
|
+ constexpr char KEY_REBUILD[] = "REBUILD";
|
|
+ constexpr char KEY_COMPILER_FLAGS[] = "COMPILATION_OPTIONS";
|
|
+ constexpr char KEY_LINKER_FLAGS[] = "LINK_OPTIONS";
|
|
}
|
|
|
|
namespace library {
|
|
diff --git a/source/intercept/source/report/wrapper/Application.cc b/source/intercept/source/report/wrapper/Application.cc
|
|
index bb36d91..358d2dc 100644
|
|
--- a/source/intercept/source/report/wrapper/Application.cc
|
|
+++ b/source/intercept/source/report/wrapper/Application.cc
|
|
@@ -129,8 +129,77 @@ namespace {
|
|
}
|
|
}
|
|
|
|
+namespace {
|
|
+ auto lamd_is_compiler_call = [](const fs::path& program) {
|
|
+ static const auto pattern = std::regex(
|
|
+ R"(^(cc|c\+\+|cxx|CC|(([^-]*-)*([mg](cc|\+\+)|[g]?fortran)(-?\d+(\.\d+){0,2})?))$)");
|
|
+ std::cmatch m;
|
|
+ return std::regex_match(program.filename().c_str(), m, pattern);
|
|
+ };
|
|
+
|
|
+ auto lamd_is_linker_call = [](const fs::path& program) {
|
|
+ static const auto pattern = std::regex(
|
|
+ R"(^(([^-]*-)*(ld|lld|ld\.bfd|ld\.gold))$)");
|
|
+ std::cmatch m;
|
|
+ return std::regex_match(program.filename().c_str(), m, pattern);
|
|
+ };
|
|
+}
|
|
+
|
|
namespace wr {
|
|
|
|
+ WrapperBuilder::WrapperBuilder(fs::path program, const std::map<std::string, std::string>& environment)
|
|
+ : Process::Builder::Builder(std::move(program))
|
|
+ , compile_flags_()
|
|
+ , ld_flags_()
|
|
+ , parameters_replace_()
|
|
+ {
|
|
+ environment_ = environment;
|
|
+ }
|
|
+
|
|
+ std::list<std::string> WrapperBuilder::split_optons(std::string& options)
|
|
+ {
|
|
+ std::list<std::string> option_new;
|
|
+ std::istringstream ss(options);
|
|
+ std::string temp;
|
|
+ while (ss >> temp) {
|
|
+ option_new.push_back(temp);
|
|
+ }
|
|
+ return option_new;
|
|
+ }
|
|
+
|
|
+ Execution WrapperBuilder::get_new_execution(Execution& execution)
|
|
+ {
|
|
+ return Execution {
|
|
+ fs::path(execution.executable),
|
|
+ parameters_replace_,
|
|
+ fs::path(execution.working_dir),
|
|
+ std::map(execution.environment.begin(), execution.environment.end())
|
|
+ };
|
|
+ }
|
|
+
|
|
+ WrapperBuilder& WrapperBuilder::get_options_from_environment()
|
|
+ {
|
|
+ if (const auto it = environment_.find(cmd::wrapper::KEY_COMPILER_FLAGS); it != environment_.end()) {
|
|
+ compile_flags_ = split_optons(it->second);
|
|
+ }
|
|
+ if (const auto it = environment_.find(cmd::wrapper::KEY_LINKER_FLAGS); it != environment_.end()) {
|
|
+ ld_flags_ = split_optons(it->second);
|
|
+ }
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
+ WrapperBuilder& WrapperBuilder::add_arguments_new()
|
|
+ {
|
|
+ get_options_from_environment();
|
|
+ parameters_replace_.swap(parameters_);
|
|
+ if (lamd_is_compiler_call(program_)) {
|
|
+ parameters_replace_.insert(parameters_replace_.end(), compile_flags_.begin(), compile_flags_.end());
|
|
+ } else if (lamd_is_linker_call(program_)) {
|
|
+ parameters_replace_.insert(parameters_replace_.end(), ld_flags_.begin(), ld_flags_.end());
|
|
+ }
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
Command::Command(wr::SessionLocator session, wr::Execution execution) noexcept
|
|
: ps::Command()
|
|
, session_(std::move(session))
|
|
@@ -141,35 +210,81 @@ namespace wr {
|
|
wr::EventReporter event_reporter(session_);
|
|
wr::SupervisorClient supervisor_client(session_);
|
|
|
|
- return supervisor_client.resolve(execution_)
|
|
- .and_then<sys::Process>([&event_reporter](auto execution) {
|
|
- return sys::Process::Builder(execution.executable)
|
|
- .add_arguments(execution.arguments.begin(), execution.arguments.end())
|
|
- .set_environment(execution.environment)
|
|
+ auto lmd_wrapper_builder = [&event_reporter](auto execution) {
|
|
+ return wr::WrapperBuilder(execution.executable, execution.environment)
|
|
+ .add_arguments(execution.arguments.begin(), execution.arguments.end())
|
|
#ifdef SUPPORT_PRELOAD
|
|
- .spawn_with_preload()
|
|
+ .spawn_with_preload();
|
|
#else
|
|
- .spawn()
|
|
+ .spawn();
|
|
#endif
|
|
- .on_success([&event_reporter, &execution](auto &child) {
|
|
- event_reporter.report_start(child.get_pid(), execution);
|
|
- });
|
|
- })
|
|
- .and_then<sys::ExitStatus>([&event_reporter](auto child) {
|
|
- sys::SignalForwarder guard(child);
|
|
- while (true) {
|
|
- auto status = child.wait(true)
|
|
- .on_success([&event_reporter](auto exit) {
|
|
- event_reporter.report_wait(exit);
|
|
- });
|
|
- if (is_exited(status)) {
|
|
- return status;
|
|
- }
|
|
- }
|
|
- })
|
|
- .map<int>([](auto status) {
|
|
- return status.code().value_or(EXIT_FAILURE);
|
|
+ };
|
|
+
|
|
+ auto lmd_builder = [&event_reporter](auto execution) {
|
|
+ return sys::Process::Builder(execution.executable)
|
|
+ .add_arguments(execution.arguments.begin(), execution.arguments.end())
|
|
+ .set_environment(execution.environment)
|
|
+#ifdef SUPPORT_PRELOAD
|
|
+ .spawn_with_preload()
|
|
+#else
|
|
+ .spawn()
|
|
+#endif
|
|
+ .on_success([&event_reporter, &execution](auto& child) {
|
|
+ event_reporter.report_start(child.get_pid(), execution);
|
|
});
|
|
+ };
|
|
+
|
|
+ auto lmd_child_wait = [&event_reporter](auto child) {
|
|
+ sys::SignalForwarder guard(child);
|
|
+ while (true) {
|
|
+ auto status = child.wait(true)
|
|
+ .on_success([&event_reporter](auto exit) {
|
|
+ event_reporter.report_wait(exit);
|
|
+ });
|
|
+ if (is_exited(status)) {
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
+ };
|
|
+ auto lmd_status_ret = [](auto status) {
|
|
+ return status.code().value_or(EXIT_FAILURE);
|
|
+ };
|
|
+
|
|
+ rust::Result<wr::Execution> result_execution = supervisor_client.resolve(execution_);
|
|
+
|
|
+ wr::Execution execution = result_execution.unwrap();
|
|
+
|
|
+ if (!lamd_is_compiler_call(execution.executable) && !lamd_is_linker_call(execution.executable)) {
|
|
+ return result_execution
|
|
+ .and_then<sys::Process>(lmd_builder)
|
|
+ .and_then<sys::ExitStatus>(lmd_child_wait)
|
|
+ .map<int>(lmd_status_ret);
|
|
+ }
|
|
+
|
|
+ auto new_execution = wr::WrapperBuilder(execution.executable, execution.environment)
|
|
+ .add_arguments(execution.arguments.begin(), execution.arguments.end())
|
|
+ .get_new_execution(execution);
|
|
+
|
|
+ auto build_spawn = result_execution.and_then<sys::Process>(lmd_wrapper_builder);
|
|
+
|
|
+ auto child_status = build_spawn.and_then<sys::ExitStatus>(lmd_child_wait)
|
|
+ .map<int>(lmd_status_ret);
|
|
+
|
|
+ if (child_status.is_ok() && !child_status.unwrap()) {
|
|
+ build_spawn.on_success([&event_reporter, &new_execution](auto& child) {
|
|
+ event_reporter.report_start(child.get_pid(), new_execution);
|
|
+ });
|
|
+ } else if (child_status.is_ok() && child_status.unwrap()) {
|
|
+ new_execution.environment[cmd::wrapper::KEY_REBUILD] = "true";
|
|
+ build_spawn.on_success([&event_reporter, &new_execution](auto& child) {
|
|
+ event_reporter.report_start(child.get_pid(), new_execution);
|
|
+ });
|
|
+ child_status = result_execution
|
|
+ .and_then<sys::Process>(lmd_builder)
|
|
+ .and_then<sys::ExitStatus>(lmd_child_wait)
|
|
+ .map<int>(lmd_status_ret);
|
|
+ }
|
|
+ return child_status;
|
|
}
|
|
|
|
Application::Application() noexcept
|
|
diff --git a/source/intercept/source/report/wrapper/Application.h b/source/intercept/source/report/wrapper/Application.h
|
|
index 06ee24d..5113be3 100644
|
|
--- a/source/intercept/source/report/wrapper/Application.h
|
|
+++ b/source/intercept/source/report/wrapper/Application.h
|
|
@@ -24,9 +24,11 @@
|
|
#include "libmain/ApplicationLogConfig.h"
|
|
#include "libflags/Flags.h"
|
|
#include "libresult/Result.h"
|
|
+#include "libsys/Process.h"
|
|
|
|
namespace wr {
|
|
using namespace domain;
|
|
+ using namespace sys;
|
|
|
|
struct Command : ps::Command {
|
|
Command(wr::SessionLocator session, wr::Execution execution) noexcept;
|
|
@@ -52,4 +54,37 @@ namespace wr {
|
|
private:
|
|
ps::ApplicationLogConfig const &log_config;
|
|
};
|
|
+
|
|
+
|
|
+ class WrapperBuilder : public Process::Builder {
|
|
+ public:
|
|
+ explicit WrapperBuilder(fs::path program, const std::map<std::string, std::string>&);
|
|
+ ~WrapperBuilder() = default;
|
|
+
|
|
+ WrapperBuilder& get_options_from_environment();
|
|
+
|
|
+ template <typename InputIt>
|
|
+ WrapperBuilder& add_arguments(InputIt first, InputIt last)
|
|
+ {
|
|
+ for (InputIt it = first; it != last; ++it) {
|
|
+ add_argument(*it);
|
|
+ }
|
|
+ add_arguments_new();
|
|
+ parameters_ = parameters_replace_;
|
|
+ return *this;
|
|
+ }
|
|
+
|
|
+ WrapperBuilder& add_arguments_new();
|
|
+
|
|
+ std::list<std::string> split_optons(std::string& options);
|
|
+
|
|
+ Execution get_new_execution(Execution& execution);
|
|
+ public:
|
|
+ NON_DEFAULT_CONSTRUCTABLE(WrapperBuilder)
|
|
+
|
|
+ private:
|
|
+ std::list<std::string> compile_flags_;
|
|
+ std::list<std::string> ld_flags_;
|
|
+ std::list<std::string> parameters_replace_;
|
|
+ };
|
|
}
|
|
diff --git a/source/libsys/include/libsys/Process.h b/source/libsys/include/libsys/Process.h
|
|
index 72c18b1..b165df3 100644
|
|
--- a/source/libsys/include/libsys/Process.h
|
|
+++ b/source/libsys/include/libsys/Process.h
|
|
@@ -29,6 +29,7 @@
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <unistd.h>
|
|
+#include <regex>
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
@@ -93,8 +94,8 @@ namespace sys {
|
|
return *this;
|
|
}
|
|
|
|
- Builder& set_environment(std::map<std::string, std::string>&&);
|
|
- Builder& set_environment(const std::map<std::string, std::string>&);
|
|
+ virtual Builder& set_environment(std::map<std::string, std::string>&&);
|
|
+ virtual Builder& set_environment(const std::map<std::string, std::string>&);
|
|
|
|
rust::Result<Process> spawn();
|
|
|
|
@@ -105,7 +106,7 @@ namespace sys {
|
|
public:
|
|
NON_DEFAULT_CONSTRUCTABLE(Builder)
|
|
|
|
- private:
|
|
+ protected:
|
|
fs::path program_;
|
|
std::list<std::string> parameters_;
|
|
std::map<std::string, std::string> environment_;
|
|
diff --git a/test/cases/compilation/output/assembly_sources.mk b/test/cases/compilation/output/assembly_sources.mk
|
|
index 857eef5..acd1770 100644
|
|
--- a/test/cases/compilation/output/assembly_sources.mk
|
|
+++ b/test/cases/compilation/output/assembly_sources.mk
|
|
@@ -3,7 +3,7 @@
|
|
# REQUIRES: make
|
|
# RUN: %{make} -C %T -f %s clean
|
|
# RUN: %{bear} --verbose --output %t.json -- %{make} -C %T -f %s
|
|
-# RUN: assert_compilation %t.json count -eq 2
|
|
+# RUN: assert_compilation %t.json count -eq 3
|
|
# RUN: assert_compilation %t.json contains -file %T/main.c -directory %T -arguments %{c_compiler} -S -o main.s main.c
|
|
# RUN: assert_compilation %t.json contains -file %T/main.s -directory %T -arguments %{c_compiler} -c -o main.o main.s
|
|
|
|
diff --git a/test/cases/compilation/output/bug439.mk b/test/cases/compilation/output/bug439.mk
|
|
index 4966289..d4d734d 100644
|
|
--- a/test/cases/compilation/output/bug439.mk
|
|
+++ b/test/cases/compilation/output/bug439.mk
|
|
@@ -4,7 +4,7 @@
|
|
# RUN: mkdir -p %T/make
|
|
# RUN: %{make} -C %T -f %s clean
|
|
# RUN: %{shell} -c "PATH=%T:$PATH %{bear} --verbose --output %t.json -- %{make} -C %T -f %s"
|
|
-# RUN: assert_compilation %t.json count -eq 2
|
|
+# RUN: assert_compilation %t.json count -eq 3
|
|
# RUN: assert_compilation %t.json contains -file %T/bug439.c -directory %T -arguments %{c_compiler} -S -o bug439.s bug439.c
|
|
# RUN: assert_compilation %t.json contains -file %T/bug439.s -directory %T -arguments %{c_compiler} -c -o bug439.o bug439.s
|
|
|
|
diff --git a/test/cases/compilation/output/compile_rebuild.sh b/test/cases/compilation/output/compile_rebuild.sh
|
|
new file mode 100644
|
|
index 0000000..6f47ae6
|
|
--- /dev/null
|
|
+++ b/test/cases/compilation/output/compile_rebuild.sh
|
|
@@ -0,0 +1,20 @@
|
|
+#!/usr/bin/env sh
|
|
+
|
|
+# REQUIRES: shell
|
|
+# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
+# RUN: assert_compilation %t.json count -ge 5
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_1.c -directory %T -arguments %{c_compiler} -c -o compile_rebuild_1.o compile_rebuild_1.c
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_1.c -directory %T -arguments %{c_compiler} -c -wrong-option -o compile_rebuild_1.o compile_rebuild_1.c
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_2.c -directory %T -arguments %{c_compiler} -c -o compile_rebuild_2.o compile_rebuild_2.c
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_2.c -directory %T -arguments %{c_compiler} -c -wrong-option -o compile_rebuild_2.o compile_rebuild_2.c
|
|
+# RUN: assert_compilation %t.json contains -file NULL_SOURCE_FOR_LD -directory %T -arguments %{ld_linker} compile_rebuild_1.o compile_rebuild_2.o -shared -q -o compile_rebuild
|
|
+
|
|
+
|
|
+touch compile_rebuild_1.c compile_rebuild_2.c
|
|
+
|
|
+export COMPILATION_OPTIONS="-wrong-option"
|
|
+export LINK_OPTIONS="-q"
|
|
+
|
|
+$CC -c -o compile_rebuild_1.o compile_rebuild_1.c
|
|
+$CC -c -o compile_rebuild_2.o compile_rebuild_2.c
|
|
+$LD -o compile_rebuild compile_rebuild_1.o compile_rebuild_2.o -shared
|
|
\ No newline at end of file
|
|
diff --git a/test/cases/compilation/output/config/filter_sources.sh b/test/cases/compilation/output/config/filter_sources.sh
|
|
deleted file mode 100644
|
|
index 2828d2e..0000000
|
|
--- a/test/cases/compilation/output/config/filter_sources.sh
|
|
+++ /dev/null
|
|
@@ -1,47 +0,0 @@
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-# REQUIRES: shell
|
|
-# RUN: %{shell} %s %t
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh
|
|
-# RUN: assert_compilation %t.json count -eq 2
|
|
-# RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c %t/source_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c %t/source_2.c
|
|
-
|
|
-TEST=$1
|
|
-
|
|
-mkdir -p $TEST;
|
|
-touch $TEST/source_1.c;
|
|
-touch $TEST/source_2.c;
|
|
-mkdir -p $TEST/exclude;
|
|
-touch $TEST/exclude/source_1.c;
|
|
-touch $TEST/exclude/source_2.c;
|
|
-
|
|
-cat > "$TEST/build.sh" << EOF
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-\$CC -c $TEST/source_1.c;
|
|
-\$CC -c $TEST/source_2.c;
|
|
-\$CC -c $TEST/exclude/source_1.c;
|
|
-\$CC -c $TEST/exclude/source_2.c;
|
|
-EOF
|
|
-
|
|
-
|
|
-cat > "$TEST/config.json" << EOF
|
|
-{
|
|
- "output": {
|
|
- "content": {
|
|
- "include_only_existing_source": true,
|
|
- "paths_to_include": [
|
|
- "$TEST"
|
|
- ],
|
|
- "paths_to_exclude": [
|
|
- "$TEST/exclude"
|
|
- ]
|
|
- },
|
|
- "format": {
|
|
- "command_as_array": true,
|
|
- "drop_output_field": true
|
|
- }
|
|
- }
|
|
-}
|
|
-EOF
|
|
diff --git a/test/cases/compilation/output/config/filter_sources_relative.sh b/test/cases/compilation/output/config/filter_sources_relative.sh
|
|
deleted file mode 100644
|
|
index db942d0..0000000
|
|
--- a/test/cases/compilation/output/config/filter_sources_relative.sh
|
|
+++ /dev/null
|
|
@@ -1,45 +0,0 @@
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-# REQUIRES: shell
|
|
-# RUN: %{shell} %s %t
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh
|
|
-# RUN: assert_compilation %t.json count -eq 2
|
|
-# RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c %t/source_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c %t/source_2.c
|
|
-
|
|
-TEST=$1
|
|
-TEST_RELATIVE=$(basename $1)
|
|
-
|
|
-mkdir -p $TEST;
|
|
-touch $TEST/source_1.c;
|
|
-touch $TEST/source_2.c;
|
|
-mkdir -p $TEST/exclude;
|
|
-touch $TEST/exclude/source_1.c;
|
|
-touch $TEST/exclude/source_2.c;
|
|
-
|
|
-cat > "$TEST/build.sh" << EOF
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-\$CC -c $TEST/source_1.c;
|
|
-\$CC -c $TEST/source_2.c;
|
|
-\$CC -c $TEST/exclude/source_1.c;
|
|
-\$CC -c $TEST/exclude/source_2.c;
|
|
-EOF
|
|
-
|
|
-
|
|
-cat > "$TEST/config.json" << EOF
|
|
-{
|
|
- "output": {
|
|
- "content": {
|
|
- "include_only_existing_source": true,
|
|
- "paths_to_exclude": [
|
|
- "$TEST_RELATIVE/exclude"
|
|
- ]
|
|
- },
|
|
- "format": {
|
|
- "command_as_array": true,
|
|
- "drop_output_field": true
|
|
- }
|
|
- }
|
|
-}
|
|
-EOF
|
|
diff --git a/test/cases/compilation/output/duplicate_entries.sh b/test/cases/compilation/output/duplicate_entries.sh
|
|
deleted file mode 100644
|
|
index 50458da..0000000
|
|
--- a/test/cases/compilation/output/duplicate_entries.sh
|
|
+++ /dev/null
|
|
@@ -1,20 +0,0 @@
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-# REQUIRES: shell
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
-# RUN: assert_compilation %t.json count -eq 4
|
|
-# RUN: assert_compilation %t.json contains -file %T/duplicate_entries_1.c -directory %T -arguments %{c_compiler} -c -o duplicate_entries_1.o duplicate_entries_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/duplicate_entries_2.c -directory %T -arguments %{c_compiler} -c -o duplicate_entries_2.o duplicate_entries_2.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/duplicate_entries_1.c -directory %T -arguments %{c_compiler} -c -D_FLAG=value -o duplicate_entries_3.o duplicate_entries_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/duplicate_entries_2.c -directory %T -arguments %{c_compiler} -c -D_FLAG=value -o duplicate_entries_4.o duplicate_entries_2.c
|
|
-
|
|
-touch duplicate_entries_1.c duplicate_entries_2.c
|
|
-
|
|
-$CC -c duplicate_entries_1.c -o duplicate_entries_1.o;
|
|
-$CC -c duplicate_entries_2.c -o duplicate_entries_2.o;
|
|
-$CC -c duplicate_entries_1.c -o duplicate_entries_3.o -D_FLAG=value;
|
|
-$CC -c duplicate_entries_2.c -o duplicate_entries_4.o -D_FLAG=value;
|
|
-$CC -c duplicate_entries_1.c -o duplicate_entries_1.o;
|
|
-$CC -c duplicate_entries_2.c -o duplicate_entries_2.o;
|
|
-$CC -c duplicate_entries_1.c -o duplicate_entries_3.o -D_FLAG=value;
|
|
-$CC -c duplicate_entries_2.c -o duplicate_entries_4.o -D_FLAG=value;
|
|
diff --git a/test/cases/compilation/output/flag/append.sh b/test/cases/compilation/output/flag/append.sh
|
|
deleted file mode 100644
|
|
index 1be8fff..0000000
|
|
--- a/test/cases/compilation/output/flag/append.sh
|
|
+++ /dev/null
|
|
@@ -1,56 +0,0 @@
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-# REQUIRES: shell
|
|
-
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s -build
|
|
-# RUN: assert_compilation %t.json count -eq 2
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/src/source_1.c -directory %T -arguments %{c_compiler} -c -o append/src/source_1.o append/src/source_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/src/source_2.c -directory %T -arguments %{c_compiler} -c -o append/src/source_2.o append/src/source_2.c
|
|
-
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json --append -- %{shell} %s -test
|
|
-# RUN: assert_compilation %t.json count -eq 4
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/src/source_1.c -directory %T -arguments %{c_compiler} -c -o append/src/source_1.o append/src/source_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/src/source_2.c -directory %T -arguments %{c_compiler} -c -o append/src/source_2.o append/src/source_2.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/test/source_1.c -directory %T -arguments %{c_compiler} -c -o append/test/source_1.o append/test/source_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/append/test/source_2.c -directory %T -arguments %{c_compiler} -c -o append/test/source_2.o append/test/source_2.c
|
|
-
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json --append -- %{shell} %s -clean
|
|
-# RUN: assert_compilation %t.json count -eq 0
|
|
-
|
|
-build()
|
|
-{
|
|
- mkdir -p append append/src
|
|
- touch append/src/source_1.c append/src/source_2.c
|
|
- $CC -c -o append/src/source_1.o append/src/source_1.c
|
|
- $CC -c -o append/src/source_2.o append/src/source_2.c
|
|
-}
|
|
-
|
|
-verify()
|
|
-{
|
|
- mkdir -p append append/test
|
|
- touch append/test/source_1.c append/test/source_2.c
|
|
- $CC -c -o append/test/source_1.o append/test/source_1.c
|
|
- $CC -c -o append/test/source_2.o append/test/source_2.c
|
|
-}
|
|
-
|
|
-clean()
|
|
-{
|
|
- rm -rf append
|
|
-}
|
|
-
|
|
-case $1 in
|
|
- -build)
|
|
- build
|
|
- ;;
|
|
- -test)
|
|
- verify
|
|
- ;;
|
|
- -clean)
|
|
- clean
|
|
- ;;
|
|
- *)
|
|
- # unknown option
|
|
- ;;
|
|
-esac
|
|
-
|
|
-true
|
|
diff --git a/test/cases/compilation/output/flag/use_ld.sh b/test/cases/compilation/output/flag/use_ld.sh
|
|
new file mode 100644
|
|
index 0000000..19031cb
|
|
--- /dev/null
|
|
+++ b/test/cases/compilation/output/flag/use_ld.sh
|
|
@@ -0,0 +1,14 @@
|
|
+#!/usr/bin/env sh
|
|
+
|
|
+# REQUIRES: shell
|
|
+
|
|
+# RUN: cd %T; %{bear} --verbose --force-preload --output %t.known.json -- %{shell} %s
|
|
+# RUN: assert_compilation %t.known.json count -eq 3
|
|
+# RUN: assert_compilation %t.known.json contains -file NULL_SOURCE_FOR_LD -directory %T -arguments %{ld_linker} use_ld_1.o use_ld_2.o -shared -o use_ld
|
|
+
|
|
+
|
|
+touch use_ld_1.c use_ld_2.c
|
|
+
|
|
+$CC -c -o use_ld_1.o use_ld_1.c;
|
|
+$CC -c -o use_ld_2.o use_ld_2.c;
|
|
+$LD use_ld_1.o use_ld_2.o -shared -o use_ld
|
|
diff --git a/test/cases/citnames/output/convert_format.sh b/test/cases/citnames/output/convert_format.sh
|
|
index eb9df14..f0a7a96 100644
|
|
--- a/test/cases/citnames/output/convert_format.sh
|
|
+++ b/test/cases/citnames/output/convert_format.sh
|
|
@@ -43,7 +43,8 @@ cat > "$1.compilations.json" << EOF
|
|
],
|
|
"directory": "/home/user",
|
|
"file": "/home/user/broken_build.c",
|
|
- "output": "/home/user/broken_build.o"
|
|
+ "output": "/home/user/broken_build.o",
|
|
+ "rebuild": true
|
|
}
|
|
]
|
|
EOF
|
|
diff --git a/test/cases/compilation/output/flags_filtered_link.sh b/test/cases/compilation/output/flags_filtered_link.sh
|
|
deleted file mode 100644
|
|
index a322f94..0000000
|
|
--- a/test/cases/compilation/output/flags_filtered_link.sh
|
|
+++ /dev/null
|
|
@@ -1,30 +0,0 @@
|
|
-#!/usr/bin/env sh
|
|
-
|
|
-# REQUIRES: shell
|
|
-# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
-# RUN: assert_compilation %t.json count -eq 4
|
|
-# RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_1.c -directory %T -arguments %{c_compiler} -c -fpic -o flags_filtered_link_1.o flags_filtered_link_1.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_2.c -directory %T -arguments %{c_compiler} -c -fpic -o flags_filtered_link_2.o flags_filtered_link_2.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_3.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_link_3 flags_filtered_link_3.c
|
|
-# RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_4.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_link_4 flags_filtered_link_4.c
|
|
-
|
|
-# set up platform specific linker options
|
|
-PREFIX="foobar";
|
|
-if [ $(uname | grep -i "darwin") ]; then
|
|
- LD_FLAGS="-o lib${PREFIX}.dylib -dynamiclib -install_name @rpath/${PREFIX}"
|
|
-else
|
|
- LD_FLAGS="-o lib${PREFIX}.so -shared -Wl,-soname,${PREFIX}"
|
|
-fi
|
|
-
|
|
-# create the source files
|
|
-echo "int foo() { return 2; }" > flags_filtered_link_1.c;
|
|
-echo "int bar() { return 2; }" > flags_filtered_link_2.c;
|
|
-echo "int main() { return 0; }" > flags_filtered_link_3.c;
|
|
-echo "int main() { return 0; }" > flags_filtered_link_4.c;
|
|
-
|
|
-$CC -c -o flags_filtered_link_1.o -fpic flags_filtered_link_1.c;
|
|
-$CC -c -o flags_filtered_link_2.o -fpic flags_filtered_link_2.c;
|
|
-$CC ${LD_FLAGS} flags_filtered_link_1.o flags_filtered_link_2.o;
|
|
-
|
|
-$CC -o flags_filtered_link_3 -l${PREFIX} -L. flags_filtered_link_3.c;
|
|
-$CC -o flags_filtered_link_4 -l ${PREFIX} -L . flags_filtered_link_4.c;
|
|
diff --git a/test/cases/compilation/output/link_rebuild.sh b/test/cases/compilation/output/link_rebuild.sh
|
|
new file mode 100644
|
|
index 0000000..3c260d9
|
|
--- /dev/null
|
|
+++ b/test/cases/compilation/output/link_rebuild.sh
|
|
@@ -0,0 +1,19 @@
|
|
+#!/usr/bin/env sh
|
|
+
|
|
+# REQUIRES: shell
|
|
+# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
+# RUN: assert_compilation %t.json count -ge 4
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_1.c -directory %T -arguments %{c_compiler} -c -Wl,-q -o compile_rebuild_1.o compile_rebuild_1.c
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild_2.c -directory %T -arguments %{c_compiler} -c -Wl,-q -o compile_rebuild_2.o compile_rebuild_2.c
|
|
+# RUN: assert_compilation %t.json contains -file NULL_SOURCE_FOR_LD -directory %T -arguments %{ld_linker} compile_rebuild_1.o compile_rebuild_2.o -shared -wrong-option -o compile_rebuild
|
|
+# RUN: assert_compilation %t.json contains -file NULL_SOURCE_FOR_LD -directory %T -arguments %{ld_linker} compile_rebuild_1.o compile_rebuild_2.o -shared -o compile_rebuild
|
|
+
|
|
+
|
|
+touch compile_rebuild_1.c compile_rebuild_2.c
|
|
+
|
|
+export COMPILATION_OPTIONS="-Wl,-q"
|
|
+export LINK_OPTIONS="-wrong-option"
|
|
+
|
|
+$CC -c -o compile_rebuild_1.o compile_rebuild_1.c
|
|
+$CC -c -o compile_rebuild_2.o compile_rebuild_2.c
|
|
+$LD -o compile_rebuild compile_rebuild_1.o compile_rebuild_2.o -shared
|
|
\ No newline at end of file
|
|
diff --git a/test/cases/compilation/output/multiple_source_build.sh b/test/cases/compilation/output/multiple_source_build.sh
|
|
index 5a7f6e0..677523a 100644
|
|
--- a/test/cases/compilation/output/multiple_source_build.sh
|
|
+++ b/test/cases/compilation/output/multiple_source_build.sh
|
|
@@ -2,7 +2,7 @@
|
|
|
|
# REQUIRES: shell
|
|
# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
-# RUN: assert_compilation %t.json count -eq 3
|
|
+# RUN: assert_compilation %t.json count -eq 4
|
|
# RUN: assert_compilation %t.json contains -file %T/multiple_source_build_1.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_1.c
|
|
# RUN: assert_compilation %t.json contains -file %T/multiple_source_build_2.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_2.c
|
|
# RUN: assert_compilation %t.json contains -file %T/multiple_source_build_3.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_3.c
|
|
diff --git a/test/cases/compilation/output/spli_option_from_environment.sh b/test/cases/compilation/output/spli_option_from_environment.sh
|
|
new file mode 100644
|
|
index 0000000..e7b74cb
|
|
--- /dev/null
|
|
+++ b/test/cases/compilation/output/spli_option_from_environment.sh
|
|
@@ -0,0 +1,13 @@
|
|
+#!/usr/bin/env sh
|
|
+
|
|
+# REQUIRES: shell
|
|
+# RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s
|
|
+# RUN: assert_compilation %t.json count -ge 1
|
|
+# RUN: assert_compilation %t.json contains -file %T/compile_rebuild.c -directory %T -arguments %{c_compiler} -c -Wl,-q -w -g3 -O0 -o compile_rebuild.o compile_rebuild.c
|
|
+
|
|
+
|
|
+touch compile_rebuild.c
|
|
+
|
|
+export COMPILATION_OPTIONS="-Wl,-q -w -g3 -O0"
|
|
+
|
|
+$CC -c -o compile_rebuild.o compile_rebuild.c
|
|
\ No newline at end of file
|
|
diff --git a/test/lit.cfg b/test/lit.cfg
|
|
index d6b474b..64fe120 100644
|
|
--- a/test/lit.cfg
|
|
+++ b/test/lit.cfg
|
|
@@ -146,6 +146,11 @@ if which('c++'):
|
|
config.substitutions.append(('%{cxx_compiler}', path))
|
|
config.environment['CXX'] = path
|
|
|
|
+# check if ld is available
|
|
+if which('ld'):
|
|
+ path = which('ld')
|
|
+ config.substitutions.append(('%{ld_linker}', path))
|
|
+ config.environment['LD'] = path
|
|
|
|
# check if fortran compiler is available
|
|
if which('gfortran'):
|