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
10 changes: 7 additions & 3 deletions .github/workflows/ubuntu_latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ on:
pull_request:
branches: [ master ]

env:
CURL_GET: curl -fL --retry 3 --retry-delay 2
PATH_GET: https://github.com/mkn/mkn/releases/download/latest

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6

- run: sudo apt-get install iwyu

- run: |
curl -Lo mkn https://github.com/mkn/mkn/releases/download/latest/mkn_nix
$CURL_GET -o mkn ${PATH_GET}/mkn_nix
chmod +x mkn
KLOG=3 ./mkn clean build -dtOp iwyu -a "-std=c++17 -fPIC"
KLOG=3 ./mkn clean build -dtOp iwyu -a "-std=c++20 -fPIC"

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
bin
.mkn
.clangd
6 changes: 6 additions & 0 deletions .sublime-project
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
],
"settings":
{
"ClangFormat" :
{
"binary" : "clang-format",
"format_on_save" : true,
"style" : "file"
}
}
}

Expand Down
37 changes: 0 additions & 37 deletions .travis.yml

This file was deleted.

7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

** Compile stage plugin to to run include-what-you-use on all applicable files **

[![Travis](https://travis-ci.org/mkn-mod/cpp.iwyu.svg?branch=master)](https://travis-ci.org/mkn-mod/cpp.iwyu)

## Prerequisites
[maiken](https://github.com/Dekken/maiken)
[maiken](https://github.com/mkn/mkn)

## Usage

Expand All @@ -18,8 +16,7 @@ mod:
inc: inc/1 inc/2 # additional include directories
paths: search/dir # scan directories
ignore: src/python3 # if file found has path that contains string ignore


types: cpp hpp cc # file types checked default: {"cpp", "cxx", "cc", "cc", "h", "hpp"}

```

Expand Down
4 changes: 2 additions & 2 deletions mkn.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ mode: shared

profile:
- name: base
dep: mkn#${version}&${maiken_location}(${maiken_scm})[mod]
dep: mkn.mod mkn#${version}&${maiken_location}(${maiken_scm})[headers]
if_arg:
win_shared: -DYAML_CPP_DLL
shared: -DKUL_SHARED
shared: -DMKN_KUL_SHARED

- name: format
mod: |
Expand Down
119 changes: 54 additions & 65 deletions mod.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
Copyright (c) 2013, Philip Deegan.
Copyright (c) 2026, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -28,101 +28,92 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "mkn/mod/init.hpp" // IWYU pragma: keep

#include <stdint.h> // for uint16_t
#include <string> // for string, allocator, operator+, basic_...
#include <unordered_set> // for unordered_set
#include <utility> // for pair
#include <vector> // for vector
#include "mkn/kul/cli.hpp" // for asArgs
#include "mkn/kul/defs.hpp" // for KUL_PUBLISH
#include "mkn/kul/except.hpp" // for Exception, KEXCEPT, KTHROW
#include "mkn/kul/log.hpp" // for KLOG, KLOG_INF, KLOG_DBG
#include "mkn/kul/map.hpp" // for Map
#include "mkn/kul/os.hpp" // for Dir, File, WHICH, Exception, PushDir
#include "mkn/kul/proc.hpp" // for Process, AProcess, ExitException
#include "mkn/kul/string.hpp" // for String
#include "mkn/kul/yaml.hpp" // for NodeValidator, Validator, yaml
#include "maiken/app.hpp" // for Application
#include "maiken/module.hpp" // for Module
#include "maiken/module/init.hpp"// IWYU pragma: keep
#include "maiken/project.hpp" // for Project
#include "maiken/source.hpp" // for Source
#include "mkn/kul/cli.hpp" // for asArgs
#include "mkn/kul/defs.hpp" // for MKN_KUL_PUBLISH
#include "mkn/kul/except.hpp" // for Exception, KEXCEPT, KTHROW
#include "mkn/kul/log.hpp" // for KLOG, KLOG_INF, KLOG_DBG
#include "mkn/kul/map.hpp" // for Map
#include "mkn/kul/os.hpp" // for Dir, File, WHICH, Exception, PushDir
#include "mkn/kul/proc.hpp" // for Process, AProcess, ExitException
#include "mkn/kul/string.hpp" // for String
#include "mkn/kul/yaml.hpp" // for NodeValidator, Validator, yaml
#include "yaml-cpp/node/impl.h" // for Node::operator[], Node::Scalar
#include "yaml-cpp/node/node.h" // for Node

namespace mkn::mod::iwyu {
namespace mkn::mod::cpp::iwyu {

class Exception : public mkn::kul::Exception {
class Module : public mkn::mod::Module {
public:
Exception(char const* f, uint16_t const& l, std::string const& s)
: mkn::kul::Exception(f, l, s) {}
};
}

namespace mkn {

class CPP_IWYU_Module : public maiken::Module {
public:
void compile(maiken::Application& a, YAML::Node const& node) KTHROW(std::exception) override {
run(a, node);
}
void compile(mkn::mod::Context& ctx, YAML::Node const& node) override { run(ctx, node); }

protected:
using App = maiken::Application&;

static std::string find_iwyu(){
static std::string find_iwyu() {
std::vector<std::string> iwyu{"iwyu", "include-what-you-use"};
for(auto const& str : iwyu)
if(mkn::kul::env::WHICH(str)) return str;
KEXCEPT(mkn::mod::iwyu::Exception, "Failed to find valid iwyu binary, check PATH");
for (auto const& str : iwyu)
if (kul::env::WHICH(str)) return str;
KEXCEPT(Exception, "Failed to find valid iwyu binary, check PATH");
}

static void VALIDATE_NODE(YAML::Node const& node) {
using namespace mkn::kul::yaml;
using namespace kul::yaml;
Validator({NodeValidator("inc"), NodeValidator("args"), NodeValidator("ignore"),
NodeValidator("headers"),
NodeValidator("paths"), NodeValidator("types")})
NodeValidator("headers"), NodeValidator("paths"), NodeValidator("types")})
.validate(node);
}

template <typename C_Unit>
void CHECK(std::string const& proc, C_Unit c_unit, mkn::kul::File&& f, YAML::Node const& node) {
if (node["ignore"]) if(f.escm().find(node["ignore"].Scalar()) != std::string::npos) return;
void CHECK(std::string const& proc, std::string const& compileCmd, kul::File&& f,
YAML::Node const& node) {
if (node["ignore"])
if (f.escm().find(node["ignore"].Scalar()) != std::string::npos) return;

mkn::kul::Process p(proc);
auto compileStr = c_unit.compileString().substr(c_unit.compiler.size());
kul::Process p(proc);
auto const firstSpace = compileCmd.find(' ');
auto compileStr =
firstSpace == std::string::npos ? std::string() : compileCmd.substr(firstSpace + 1);
p << compileStr.substr(0, compileStr.rfind(" -o"));
if (node["args"]) p << node["args"].Scalar();
if (node["inc"]) for (const auto& inc : node["inc"].Scalar()) p << std::string{"-I"}+inc;
if (node["inc"])
for (const auto& inc : mkn::kul::cli::asArgs(node["inc"].Scalar()))
p << std::string{"-I"} + inc;
if (node["headers"]) p << node["headers"].Scalar();
p << f.escm();
KLOG(DBG) << p;
try{
try {
p.start();
}catch(mkn::kul::proc::ExitException const& e){}
} catch (kul::proc::ExitException const& e) {
}
}
void run(App& a, YAML::Node const& node) KTHROW(std::exception) {
void run(mkn::mod::Context& ctx, YAML::Node const& node) KTHROW(std::exception) {
VALIDATE_NODE(node);
mkn::kul::os::PushDir pushd(a.project().dir());
auto const state = ctx.state();
kul::os::PushDir pushd(state.projectDir);

std::unordered_set<std::string> types;
if (!node["types"]) {
types = {"cpp", "cxx", "cc", "cc", "h", "hpp"};
} else
for (const auto& s : mkn::kul::String::SPLIT(node["types"].Scalar(), ":")) types.insert(s);
for (const auto& s : kul::String::SPLIT(node["types"].Scalar(), ":")) types.insert(s);

std::unordered_set<std::string> files;

const auto sources = a.sourceMap();
for (const auto& p1 : sources)
if (types.count(p1.first))
for (const auto& p2 : p1.second)
for (const auto& p3 : p2.second) files.insert(p3.in());
for (const auto& f : state.sourceFiles) {
auto const dot = f.rfind(".");
if (dot == std::string::npos) continue;
if (types.count(f.substr(dot + 1))) files.insert(f);
}

if (node["paths"]){
for (const auto& path : mkn::kul::cli::asArgs(node["paths"].Scalar())) {
mkn::kul::Dir d(path);
if (!d) KEXCEPT(mkn::kul::fs::Exception, "Directory does not exist: ") << d.path();
if (node["paths"]) {
for (const auto& path : kul::cli::asArgs(node["paths"].Scalar())) {
kul::Dir d(path);
if (!d) KEXCEPT(kul::fs::Exception, "Directory does not exist: ", d.path());
for (const auto& file : d.files(1)) {
const std::string name = file.name();
if (name.find(".") == std::string::npos) continue;
Expand All @@ -133,17 +124,15 @@ class CPP_IWYU_Module : public maiken::Module {
}

auto proc = find_iwyu();
maiken::ThreadingCompiler tc(a);
using Pair = std::pair<maiken::Source, std::string>;
for (const auto& file : files)
CHECK(proc, tc.compilationUnit(Pair{mkn::kul::File(file).escm()+".cpp", "obj"}), mkn::kul::File(file), node);
CHECK(proc, ctx.compileCommandFor(kul::File(file).escm() + ".cpp"), kul::File(file), node);
}
};

} // namespace mkn
} // namespace mkn::mod::cpp::iwyu

extern "C" KUL_PUBLISH maiken::Module *maiken_module_construct() {
return new mkn::CPP_IWYU_Module;
extern "C" MKN_KUL_PUBLISH mkn::mod::Module* maiken_module_construct() {
return new mkn::mod::cpp::iwyu::Module;
}

extern "C" KUL_PUBLISH void maiken_module_destruct(maiken::Module *p) { delete p; }
extern "C" MKN_KUL_PUBLISH void maiken_module_destruct(mkn::mod::Module* p) { delete p; }