Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/citnames/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ target_sources(citnames_a
PRIVATE
source/Citnames.cc
source/semantic/Build.cc
source/semantic/Common.cc
source/semantic/Parsers.cc
source/semantic/Semantic.cc
source/semantic/ToolAny.cc
source/semantic/ToolClang.cc
source/semantic/ToolCuda.cc
source/semantic/ToolGcc.cc
source/semantic/ToolIntelFortran.cc
source/semantic/ToolWrapper.cc
source/semantic/ToolExtendingWrapper.cc
INTERFACE
Expand Down Expand Up @@ -66,6 +68,7 @@ if (ENABLE_UNIT_TESTS)
test/ParserTest.cc
test/ToolClangTest.cc
test/ToolGccTest.cc
test/ToolIntelFortranTest.cc
test/ToolWrapperTest.cc
)

Expand Down
2 changes: 2 additions & 0 deletions source/citnames/source/semantic/Build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "ToolGcc.h"
#include "ToolClang.h"
#include "ToolCuda.h"
#include "ToolIntelFortran.h"
#include "ToolWrapper.h"
#include "ToolExtendingWrapper.h"
#include "Convert.h"
Expand All @@ -44,6 +45,7 @@ namespace {
std::make_shared<cs::semantic::ToolClang>(),
std::make_shared<cs::semantic::ToolWrapper>(),
std::make_shared<cs::semantic::ToolCuda>(),
std::make_shared<cs::semantic::ToolIntelFortran>(),
};
for (auto && compiler : cfg.compilers_to_recognize) {
tools.emplace_front(std::make_shared<cs::semantic::ToolExtendingWrapper>(std::move(compiler)));
Expand Down
124 changes: 124 additions & 0 deletions source/citnames/source/semantic/Common.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/* Copyright (C) 2012-2024 by László Nagy
This file is part of Bear.

Bear is a tool to generate compilation database for clang tooling.

Bear is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Bear is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "Common.h"

#include <string_view>
#include <tuple>

using namespace cs::semantic;

namespace {

std::tuple<
Arguments,
std::vector<fs::path>,
std::optional<fs::path>>
split(const CompilerFlags& flags)
{
Arguments arguments;
std::vector<fs::path> sources;
std::optional<fs::path> output;

for (const auto& flag : flags) {
switch (flag.type) {
case CompilerFlagType::SOURCE: {
auto candidate = fs::path(flag.arguments.front());
sources.emplace_back(std::move(candidate));
break;
}
case CompilerFlagType::KIND_OF_OUTPUT_OUTPUT: {
auto candidate = fs::path(flag.arguments.back());
output = std::make_optional(std::move(candidate));
break;
}
case CompilerFlagType::LINKER:
case CompilerFlagType::PREPROCESSOR_MAKE:
case CompilerFlagType::DIRECTORY_SEARCH_LINKER:
break;
default: {
std::copy(flag.arguments.begin(), flag.arguments.end(), std::back_inserter(arguments));
break;
}
}
}
return std::make_tuple(arguments, sources, output);
}

bool is_compiler_query(const CompilerFlags& flags)
{
// no flag is a no compilation
if (flags.empty()) {
return true;
}
// otherwise check if this was a version query of a help
return std::any_of(flags.begin(), flags.end(), [](const auto& flag) {
return (flag.type == CompilerFlagType::KIND_OF_OUTPUT_INFO);
});
}

bool linking(const CompilerFlags& flags)
{
return std::none_of(flags.begin(), flags.end(), [](auto flag) {
return (flag.type == CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING);
});
}
}

rust::Result<SemanticPtr> cs::semantic::compilation_impl(const FlagsByName& flags, const Execution& execution,
std::function<Arguments(const Execution&)> create_argument_list_func,
std::function<bool(const CompilerFlags&)> is_preprocessor_func)
{
const auto& parser = Repeat(
OneOf(
FlagParser(flags),
SourceMatcher(),
EverythingElseFlagMatcher()));

const Arguments& input_arguments = create_argument_list_func(execution);
return parse(parser, input_arguments)
.and_then<SemanticPtr>([&execution, is_preprocessor_func](auto flags) -> rust::Result<SemanticPtr> {
if (is_compiler_query(flags)) {
SemanticPtr result = std::make_shared<QueryCompiler>();
return rust::Ok(std::move(result));
}
if (is_preprocessor_func(flags)) {
SemanticPtr result = std::make_shared<Preprocess>();
return rust::Ok(std::move(result));
}

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");
}

SemanticPtr result = std::make_shared<Compile>(
execution.working_dir,
execution.executable,
std::move(arguments),
std::move(sources),
std::move(output));
return rust::Ok(std::move(result));
});
}
31 changes: 31 additions & 0 deletions source/citnames/source/semantic/Common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright (C) 2012-2024 by László Nagy
This file is part of Bear.

Bear is a tool to generate compilation database for clang tooling.

Bear is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Bear is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "Semantic.h"
#include "Parsers.h"

#include "libresult/Result.h"

namespace cs::semantic {
rust::Result<SemanticPtr> compilation_impl(const FlagsByName& flags, const Execution& execution,
std::function<Arguments(const Execution&)> create_argument_list_func,
std::function<bool(const CompilerFlags&)> is_preprocessor_func);
}
98 changes: 4 additions & 94 deletions source/citnames/source/semantic/ToolGcc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "ToolGcc.h"
#include "Parsers.h"
#include "Common.h"

#include "libsys/Path.h"

Expand Down Expand Up @@ -68,18 +69,6 @@ namespace {
return input_arguments;
}

bool is_compiler_query(const CompilerFlags& flags)
{
// no flag is a no compilation
if (flags.empty()) {
return true;
}
// otherwise check if this was a version query of a help
return std::any_of(flags.begin(), flags.end(), [](const auto& flag) {
return (flag.type == CompilerFlagType::KIND_OF_OUTPUT_INFO);
});
}

bool is_prerpocessor(const CompilerFlags& flags)
{
// one of those make dependency generation also not count as compilation.
Expand All @@ -93,47 +82,6 @@ namespace {
|| ((flag.type == CompilerFlagType::PREPROCESSOR_MAKE) && (NO_COMPILATION_FLAG.find(candidate) != NO_COMPILATION_FLAG.end()));
});
}

bool linking(const CompilerFlags& flags)
{
return std::none_of(flags.begin(), flags.end(), [](auto flag) {
return (flag.type == CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING);
});
}

std::tuple<
Arguments,
std::vector<fs::path>,
std::optional<fs::path>
> split(const CompilerFlags &flags) {
Arguments arguments;
std::vector<fs::path> sources;
std::optional<fs::path> output;

for (const auto &flag : flags) {
switch (flag.type) {
case CompilerFlagType::SOURCE: {
auto candidate = fs::path(flag.arguments.front());
sources.emplace_back(std::move(candidate));
break;
}
case CompilerFlagType::KIND_OF_OUTPUT_OUTPUT: {
auto candidate = fs::path(flag.arguments.back());
output = std::make_optional(std::move(candidate));
break;
}
case CompilerFlagType::LINKER:
case CompilerFlagType::PREPROCESSOR_MAKE:
case CompilerFlagType::DIRECTORY_SEARCH_LINKER:
break;
default: {
std::copy(flag.arguments.begin(), flag.arguments.end(), std::back_inserter(arguments));
break;
}
}
}
return std::make_tuple(arguments, sources, output);
}
}

namespace cs::semantic {
Expand Down Expand Up @@ -268,46 +216,8 @@ namespace cs::semantic {
return compilation(FLAG_DEFINITION, execution);
}

rust::Result<SemanticPtr> ToolGcc::compilation(const FlagsByName &flags, const Execution &execution) {
const auto &parser =
Repeat(
OneOf(
FlagParser(flags),
SourceMatcher(),
EverythingElseFlagMatcher()
)
);

const Arguments &input_arguments = create_argument_list(execution);
return parse(parser, input_arguments)
.and_then<SemanticPtr>([&execution](auto flags) -> rust::Result<SemanticPtr> {
if (is_compiler_query(flags)) {
SemanticPtr result = std::make_shared<QueryCompiler>();
return rust::Ok(std::move(result));
}
if (is_prerpocessor(flags)) {
SemanticPtr result = std::make_shared<Preprocess>();
return rust::Ok(std::move(result));
}

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");
}

SemanticPtr result = std::make_shared<Compile>(
execution.working_dir,
execution.executable,
std::move(arguments),
std::move(sources),
std::move(output)
);
return rust::Ok(std::move(result));
});
rust::Result<SemanticPtr> ToolGcc::compilation(const FlagsByName& flags, const Execution& execution)
{
return compilation_impl(flags, execution, create_argument_list, is_prerpocessor);
}
}
Loading
Loading