Post

Porting Arkanjo to macOS

Porting Arkanjo to macOS

Recently I contributed to the Arkanjo project, a tool for detecting code clones. It was originally configured to run only on Linux (Ubuntu/Debian), and I took the initiative to adapt it to macOS. In this post, I’ll walk through the main issues I faced and how I solved them.


Prerequisites on macOS

These are the dependencies required to run Arkanjo on macOS. All can be installed using Homebrew:

1
2
3
4
brew install python
pip3 install nltk gensim astor
python3 -m nltk.downloader punkt
brew install jsoncpp

Main Issues and Fixes

1. #include <bits/stdc++.h>

This header is available only on Linux-based compilers. On macOS, I had to manually replace it with the specific headers used in each file — a tedious but necessary process.


2. #include <jsoncpp/json/json.h>

After installing jsoncpp via Homebrew, the include path on macOS became <json/json.h>. I automated this replacement using the command:

1
find . -name "*.hpp" -o -name "*.cpp" | xargs sed -i '' 's|<jsoncpp/json/json.h>|<json/json.h>|g'

Additionally, I updated the Makefile to correctly locate the installed headers and link the library:

1
2
CXXFLAGS = -std=c++17 -g -I/opt/homebrew/include
LDFLAGS  = -L/opt/homebrew/lib -ljsoncpp

3. Shell commands (rm) in C++ code

The original code used system calls like:

1
2
string command_rm_tmp = "rm -r -f " + base_path + "/";
system(command_rm_tmp.c_str());

I replaced this with a more secure and portable approach using C++17’s <filesystem>:

1
2
3
4
5
6
7
#include <filesystem>
namespace fs = std::filesystem;

fs::path dir_to_remove = base_path;
if (fs::exists(dir_to_remove)) {
    fs::remove_all(dir_to_remove);
}

Updated Makefile

Here is the final version of the Makefile that works correctly on macOS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
CXX = g++
CXXFLAGS = -std=c++17 -g -I/opt/homebrew/include
LDFLAGS = -L/opt/homebrew/lib -ljsoncpp

SRC_BASE = base/utils.cpp base/config.cpp base/path.cpp base/similarity_table.cpp base/function.cpp
SRC_PRE = pre/function_breaker_util.cpp pre/function_breaker_c.cpp pre/function_breaker_java.cpp pre/function_breaker.cpp pre/parser.cpp pre/duplication_finder_tool.cpp pre/duplication_finder_diff.cpp pre/preprocessor.cpp
SRC_E2E = tests/e2e/test.cpp
SRC_EXTRA = finder/similar_function_finder.cpp counter/counter_duplication_code_trie.cpp counter/counter_duplication_code.cpp explorer/similarity_explorer.cpp big_clone/big_clone_formater.cpp big_clone/big_clone_tailor_evaluator.cpp rand/random_selector.cpp orchestrator.cpp

all: exec preprocessor test

exec:
	$(CXX) $(CXXFLAGS) $(SRC_BASE) $(SRC_PRE) $(SRC_EXTRA) -o exec $(LDFLAGS)

preprocessor:
	$(CXX) $(CXXFLAGS) $(SRC_BASE) $(SRC_PRE) pre/preprocessor_main.cpp -o preprocessor $(LDFLAGS)

test:
	$(CXX) $(CXXFLAGS) $(SRC_BASE) $(SRC_PRE) $(SRC_E2E) -o test $(LDFLAGS)

clean:
	rm -f exec preprocessor test

Frequently Used Commands

These were the key commands I ran during the build process:

1
2
3
make clean
make
./preprocessor

Issue Resolved

This contribution was made to solve the following open issue:

🔗 Arkanjo Issue #4 - Adapt build for macOS


Conclusion

Porting a C++ project designed for Linux to macOS requires special attention to header compatibility, library paths, and shell command usage. It was a great learning experience and a valuable contribution to make the project cross-platform.

If you’re interested in contributing too, check out the open issues on the Arkanjo repository. Every bit of help counts!

Feel free to reach out or fork the project on GitHub! 👨🏻‍💻

This post is licensed under CC BY 4.0 by the author.