Skip to content

Commit

Permalink
Feature/nbrf (#23)
Browse files Browse the repository at this point in the history
* Add nanobind extension for nob.

* Add template to run nob command via Python and to CI.

* Add basic robot framework test.

* Start fixing memory leaks in nob (WIP, cf. TODO)

* Update duplicate code action.
  • Loading branch information
iglesias authored May 23, 2024
1 parent e6881b8 commit ac0116a
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 24 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/github-actions-duplicate-code-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ on: pull_request
jobs:
duplicate-code-check:
name: Check for duplicate code
runs-on: ubuntu-20.04
run_if:
if: startsWith(github.head_ref, 'adventofcode')
runs-on: ubuntu-latest
steps:
- name: Check for duplicate code
uses: platisd/duplicate-code-detection-tool@master
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/nanobind.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: nanobind
run-name: ${{ github.actor }} is building Python extensions with nanobind
on:
push:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: sh
working-directory: .
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: 'recursive'
#- name: Setup tmate session
# uses: mxschmitt/action-tmate@v3
# with:
# detached: true
- name: Python setup
uses: actions/setup-python@v5
with:
python-version: '3.11.9'
- name: Install Python development dependency
run: |
sudo apt-get update
sudo apt-get install python3.11-dev
python -m pip install --upgrade pip
pip install robotframework
# pip install -r requirements.txt
- name: Build
run: ./build_nb.sh
- name: Test
working-directory: ${{github.workspace}}
run: python3.11 nob.py
- name: Robot
run: PYTHONPATH=.:robot robot -d logs robot/NobTestSuite.robot
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ a.out
gcm.cache/
.ycm_extra_conf.py
__pycache__/
nobuild/
venv/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "ext/nanobind"]
path = ext/nanobind
url = https://github.com/wjakob/nanobind
11 changes: 11 additions & 0 deletions build_nb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh -x

mkdir nobuild

PYTHON_INCLUDE=`pkg-config --cflags python3`

g++ nobnb.cpp -std=c++20 -fvisibility=hidden -DNDEBUG -DNB_COMPACT_ASSERTIONS $PYTHON_INCLUDE -fPIC -Iext/nanobind/include -Iext/nanobind/ext/robin_map/include -Os -c -o nobuild/nobnb.o

g++ ext/nanobind/src/nb_combined.cpp -std=c++20 -fvisibility=hidden -DNDEBUG -DNB_COMPACT_ASSERTIONS $PYTHON_INCLUDE -fPIC -Iext/nanobind/include -Iext/nanobind/ext/robin_map/include -O3 -fno-strict-aliasing -ffunction-sections -fdata-sections -c -o nobuild/libnanobind.o

g++ -shared -Wl,-s -Wl,--gc-sections nobuild/nobnb.o nobuild/libnanobind.o -o nobuild/nob.cpython-311-x86_64-linux-gnu.so
1 change: 1 addition & 0 deletions ext/nanobind
Submodule nanobind added at 12c3c7
56 changes: 42 additions & 14 deletions nob.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
#define NOBUILD_IMPLEMENTATION
#include "./nob.h"

#include <cassert>
#include <array>
#include <cstdlib>
#include <filesystem>
#include <queue>
#include <string_view>
#include <vector>

#define CFLAGS "-Wall", "-Wextra", "-std=c2x", "-pedantic"
#define CPPFLAGS "-Wall", "-Wextra", "-std=c++23", "-pedantic", "-Wconversion"
#define CFLAGS "-std=c2x", "-Wall", "-Wextra", "-pedantic"
#define CPPFLAGS "-std=c++23", "-Wall", "-Wconversion", "-Wextra", "-pedantic", "-fsanitize=address,pointer-overflow,signed-integer-overflow,undefined"

#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)


#define MAKE_CMD(...) \
({Cmd cmd = { \
.line = cstr_array_make(__VA_ARGS__, NULL) \
}; \
Cstr cmd_to_show = cmd_show(cmd); \
INFO("MAKE_CMD: %s", cmd_to_show); \
std::free(reinterpret_cast<void*>( \
const_cast<char*>(cmd_to_show))); \
cmd;}) \


namespace fs = std::filesystem;

using namespace std::string_literals; // for operator""s
using namespace std::literals; // for operator""sv

void build_kattis_c_file(std::string_view filename) {
Cstr path = PATH("kattis", filename.data());
CMD("cc", CFLAGS, "-o", NOEXT(path), path);
void build_kattis_c_file(std::string_view path) {
Cstr noextpath = NOEXT(path.data());
CMD("cc", CFLAGS, "-o", noextpath, path.data());
std::free(reinterpret_cast<void*>(const_cast<char *>(noextpath))); // :-O
}

void build_kattis_c_files() {
for (auto const& entry : fs::directory_iterator("kattis"))
if (fs::is_regular_file(entry.path())) {
auto const filename = entry.path().filename().string();
if (filename.ends_with(".c"))
build_kattis_c_file(filename);
const std::string& path = entry.path().string();
if (path.ends_with(".c")) build_kattis_c_file(path);
}
}

Expand All @@ -45,10 +58,21 @@ void build_custom_cpp_files() {
}
}

template<size_t N>
void make_and_run_cmd(std::array<Cstr, N> strings)
{
Cmd cmd;
cmd.line.count = strings.size();
cmd.line.elems = strings.data();
//TODO FIX leaks.
INFO("make_and_run_cmd: %s", cmd_show(cmd));
cmd_run_sync(cmd);
}

void build_cpp_file(std::string_view filename)
{
Cstr path = PATH(filename.data());
CMD("g++", CPPFLAGS, "-o", NOEXT(path), path);
make_and_run_cmd(std::array{"g++", CPPFLAGS, "-o", NOEXT(path), path});
}

void build_and_run_gtest_file(std::string_view filename)
Expand All @@ -58,10 +82,14 @@ void build_and_run_gtest_file(std::string_view filename)
CMD(NOEXT(path));
}

Pid build_gtest_file_async(std::string_view filename)
Pid build_gtest_file_async(std::string_view path)
{
Cstr path = PATH(filename.data());
return cmd_run_async(MAKE_CMD("g++", CPPFLAGS, "-o", NOEXT(path), path, "-lgtest"), NULL, NULL);
Cstr noextpath = NOEXT(path.data());
Cmd cmd = MAKE_CMD("g++", CPPFLAGS, "-o", noextpath, path.data(), "-lgtest");
Pid pid = cmd_run_async(cmd, NULL, NULL);
std::free(reinterpret_cast<void*>(const_cast<char**>(cmd.line.elems)));
std::free(reinterpret_cast<void*>(const_cast<char *>(noextpath))); // :-O
return pid;
}

Pid run_gtest_file_async(std::string_view filename)
Expand Down Expand Up @@ -143,7 +171,7 @@ int main(int argc, char* argv[])
{
GO_REBUILD_URSELF(argc, argv);

//build_kattis_c_files();
build_kattis_c_files();
//build_custom_cpp_files();
//build_directory_cpp_files("adventofcode");
//build_codeforces_cpp_files();
Expand Down
15 changes: 6 additions & 9 deletions nob.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#define PATH_SEP "/"
typedef pid_t Pid;
typedef int Fd;
Expand Down Expand Up @@ -107,17 +106,15 @@ typedef struct {
Cmd cmd = { \
.line = cstr_array_make(__VA_ARGS__, NULL) \
}; \
INFO("CMD: %s", cmd_show(cmd)); \
Cstr cmd_to_show = cmd_show(cmd); \
INFO("CMD: %s", cmd_to_show); \
std::free(reinterpret_cast<void*>( \
const_cast<char*>(cmd_to_show))); \
cmd_run_sync(cmd); \
std::free(reinterpret_cast<void*>( \
const_cast<char**>(cmd.line.elems))); \
} while (0)

#define MAKE_CMD(...) \
({Cmd cmd = { \
.line = cstr_array_make(__VA_ARGS__, NULL) \
}; \
INFO("MAKE_CMD: %s", cmd_show(cmd)); \
cmd;}) \

typedef enum {
CHAIN_TOKEN_END = 0,
CHAIN_TOKEN_IN,
Expand Down
4 changes: 4 additions & 0 deletions nob.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import nobuild.nob as nob

nob.make_and_run_cmd(["ls", "--color", "-l", "-t"])
nob.make_and_run_cmd(["pwd"])
18 changes: 18 additions & 0 deletions nobnb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <utility>

#include <nanobind/nanobind.h>
#include <nanobind/stl/array.h>

#include "nob.cpp"

namespace nb = nanobind;

NB_MODULE(nob, m) {
nb::class_<Cmd>(m, "Cmd")
.def(nb::init<>())
.def_rw("line", &Cmd::line);

[&m]<std::size_t... Is>(std::index_sequence<Is...>) {
(m.def("make_and_run_cmd", &make_and_run_cmd<Is + 1>), ...);
}(std::make_index_sequence<19>{});
}
16 changes: 16 additions & 0 deletions robot/NobRobotLib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import nobuild.nob as nob
import os
import time

class NobRobotLib:
def __init__(self) -> None:
pass

def build_executable(self):
nob.make_and_run_cmd(["g++", "template.cc"])

def get_executable_time(self):
return os.path.getmtime('a.out')

def get_current_time(self):
return time.time()
8 changes: 8 additions & 0 deletions robot/NobTestSuite.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*** Settings ***
Documentation Basic nob test suite.
Resource keywords.resource

*** Test Cases ***
Test Case 1
Build file
Verify build
12 changes: 12 additions & 0 deletions robot/keywords.resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
*** Settings ***
Documentation
Library NobRobotLib

*** Keywords ***
Build file
Build executable

Verify build
${file_time}= Get Executable Time
${time}= Get current time
Should be true ${time}-${file_time} <= 1

0 comments on commit ac0116a

Please sign in to comment.