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
2 changes: 2 additions & 0 deletions source/citnames/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ target_sources(citnames_a
source/semantic/Parsers.cc
source/semantic/Semantic.cc
source/semantic/ToolAny.cc
source/semantic/ToolCrayFtnfe.cc
source/semantic/ToolClang.cc
source/semantic/ToolCuda.cc
source/semantic/ToolGcc.cc
Expand Down Expand Up @@ -66,6 +67,7 @@ if (ENABLE_UNIT_TESTS)
add_executable(citnames_unit_test
test/OutputTest.cc
test/ParserTest.cc
test/ToolCrayFtnfeTest.cc
test/ToolClangTest.cc
test/ToolGccTest.cc
test/ToolIntelFortranTest.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 @@ -20,6 +20,7 @@
#include "Build.h"
#include "ToolAny.h"
#include "ToolGcc.h"
#include "ToolCrayFtnfe.h"
#include "ToolClang.h"
#include "ToolCuda.h"
#include "ToolIntelFortran.h"
Expand All @@ -46,6 +47,7 @@ namespace {
std::make_shared<cs::semantic::ToolWrapper>(),
std::make_shared<cs::semantic::ToolCuda>(),
std::make_shared<cs::semantic::ToolIntelFortran>(),
std::make_shared<cs::semantic::ToolCrayFtnfe>(),
};
for (auto && compiler : cfg.compilers_to_recognize) {
tools.emplace_front(std::make_shared<cs::semantic::ToolExtendingWrapper>(std::move(compiler)));
Expand Down
1 change: 1 addition & 0 deletions source/citnames/source/semantic/Common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "Common.h"

#include <algorithm>
#include <string_view>
#include <tuple>

Expand Down
134 changes: 134 additions & 0 deletions source/citnames/source/semantic/ToolCrayFtnfe.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* 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 "ToolCrayFtnfe.h"
#include "Common.h"

#include <regex>
#include <set>

using namespace cs::semantic;

namespace {

Arguments create_argument_list(const Execution& execution)
{
Arguments input_arguments;
std::copy(execution.arguments.begin(), execution.arguments.end(), std::back_inserter(input_arguments));
return input_arguments;
}

bool is_preprocessor(const CompilerFlags& flags)
{
return std::any_of(flags.begin(), flags.end(), [](const auto& flag) {
const std::string& candidate = flag.arguments.front();
static const std::set<std::string_view> NO_COMPILATION_FLAG = { "-E", "-eZ", "-e Z", "-eP", "-e P" };
return ((flag.type == CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING) && (NO_COMPILATION_FLAG.find(candidate) != NO_COMPILATION_FLAG.end()))
|| ((flag.type == CompilerFlagType::PREPROCESSOR_MAKE));
});
return false;
}

}

namespace cs::semantic {

const FlagsByName ToolCrayFtnfe::FLAG_DEFINITION = {
{ "-add-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-add-rpath-shared", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-add-runpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "--as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-A", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-b", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT } },
{ "-c", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
{ "--custom-ld-script=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::LINKER } },
{ "-d", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-D", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR } },
{ "-e", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-E", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
{ "-f", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-F", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-g", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-gcc-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-G", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-h", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-I", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
{ "-J", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
{ "-K", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-l", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::LINKER } },
{ "-L", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH_LINKER } },
{ "-m", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-M", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-no-add-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-no-add-rpath-shared", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-no-add-runpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-no-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "--no-as-needed", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "--no-custom-ld-script", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-no-gcc-rpath", { MatchInstruction::EXACTLY, CompilerFlagType::LINKER } },
{ "-N", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-O", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
{ "-o", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT_OUTPUT } },
{ "-p", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
{ "-Q", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::DIRECTORY_SEARCH } },
{ "-r", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::KIND_OF_OUTPUT } },
{ "-R", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-s", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-S", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_NO_LINKING } },
{ "-T", { MatchInstruction::EXACTLY, CompilerFlagType::KIND_OF_OUTPUT_INFO } },
{ "-target-accel=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
{ "-target-cpu=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
{ "-target-network=", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED, CompilerFlagType::OTHER } },
{ "-U", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::PREPROCESSOR } },
{ "-v", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-V", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-W", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-x", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-Y", { MatchInstruction::EXACTLY_WITH_1_OPT_GLUED_OR_SEP, CompilerFlagType::OTHER } },
{ "-openmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-noopenmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-mp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-Mnoopenmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-qno-openmp", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-dynamic", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-shared", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-static", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-default64", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-VV", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-VVV", { MatchInstruction::EXACTLY, CompilerFlagType::OTHER } },
{ "-cray", { MatchInstruction::PREFIX, CompilerFlagType::OTHER } },
{ "--cray", { MatchInstruction::PREFIX, CompilerFlagType::OTHER } },
};

rust::Result<SemanticPtr> ToolCrayFtnfe::recognize(const Execution& execution) const
{
if (is_compiler_call(execution.executable)) {
return compilation_impl(FLAG_DEFINITION, execution, create_argument_list, is_preprocessor);
}
return rust::Ok(SemanticPtr());
}

bool ToolCrayFtnfe::is_compiler_call(const fs::path& program) const
{
static const auto pattern = std::regex(R"(^([^-]*-)*(ftnfe)(-?\w+(\.\d+){0,2})?$)");
std::cmatch m;
return std::regex_match(program.filename().c_str(), m, pattern);
}
}
37 changes: 37 additions & 0 deletions source/citnames/source/semantic/ToolCrayFtnfe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* 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 "Parsers.h"
#include "Tool.h"

namespace cs::semantic {

struct ToolCrayFtnfe : public Tool {

[[nodiscard]]
rust::Result<SemanticPtr> recognize(const Execution& execution) const override;

protected:
[[nodiscard]] bool is_compiler_call(const fs::path& program) const;

static const FlagsByName FLAG_DEFINITION;
};
}
96 changes: 96 additions & 0 deletions source/citnames/test/ToolCrayFtnfeTest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* 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 "gtest/gtest.h"

#include "semantic/ToolCrayFtnfe.h"

using namespace cs::semantic;

namespace {

TEST(ToolCrayFtnfe, is_compiler_call)
{
struct Expose : public ToolCrayFtnfe {
using ToolCrayFtnfe::is_compiler_call;
};
Expose sut;
EXPECT_TRUE(sut.is_compiler_call("ftnfe"));
EXPECT_TRUE(sut.is_compiler_call("/usr/bin/ftnfe"));
EXPECT_TRUE(sut.is_compiler_call("/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe"));
EXPECT_FALSE(sut.is_compiler_call("gfortran"));
EXPECT_FALSE(sut.is_compiler_call("gcc"));
// `crayftn` and `ftn` are not the real Cray Fortran compiler. `crayftn`
// and `ftn` are generic drivers that may call other compilers depending
// on the configuration of the system. The real Cray Fortran compiler is
// `ftnfe`!
EXPECT_FALSE(sut.is_compiler_call("/opt/cray/pe/cce/18.0.0/bin/crayftn"));
EXPECT_FALSE(sut.is_compiler_call("/opt/cray/pe/craype/2.7.32/bin/ftn"));
EXPECT_FALSE(sut.is_compiler_call("crayftn"));
EXPECT_FALSE(sut.is_compiler_call("ftn"));
}

TEST(ToolCrayFtnfe, fails_on_empty)
{
ToolCrayFtnfe sut;
EXPECT_TRUE(Tool::not_recognized(sut.recognize(Execution {})));
}

TEST(ToolCrayFtnfe, simple)
{
Execution input = {
"/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe",
{ "ftnfe", "-b", "source_out.o", "-r", "file.listing", "source.c" },
"/home/user/project",
{},
};
SemanticPtr expected = SemanticPtr(
new Compile(
input.working_dir,
input.executable,
{ "-c", "-r", "file.listing" },
{ fs::path("source.c") },
{ fs::path("source_out.o") }));
ToolCrayFtnfe sut;
auto result = sut.recognize(input);
EXPECT_TRUE(Tool::recognized_ok(result));
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
}

TEST(ToolCrayFtnfe, linker_flag_filtered)
{
Execution input = {
"/opt/cray/pe/cce/18.0.0/cce/x86_64/bin/ftnfe",
{ "ftnfe", "-L.", "-lthing", "-o", "exe", "source.c" },
"/home/user/project",
{},
};
SemanticPtr expected = SemanticPtr(
new Compile(
input.working_dir,
input.executable,
{ "-c" },
{ fs::path("source.c") },
{ fs::path("exe") }));
ToolCrayFtnfe sut;
auto result = sut.recognize(input);
EXPECT_TRUE(Tool::recognized_ok(result));
EXPECT_PRED2([](auto lhs, auto rhs) { return lhs->operator==(*rhs); }, expected, result.unwrap());
}
}
1 change: 1 addition & 0 deletions source/intercept/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ install(CODE "
COMMAND ln -sf ../wrapper clang
COMMAND ln -sf ../wrapper clang++
COMMAND ln -sf ../wrapper f77
COMMAND ln -sf ../wrapper ftnfe
COMMAND ln -sf ../wrapper gfortran
COMMAND ln -sf ../wrapper ifx
COMMAND ln -sf ../wrapper ifort
Expand Down
Loading