aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.nix140
-rw-r--r--include/evanix.h1
-rw-r--r--include/jobs.h3
-rw-r--r--meson.build9
-rw-r--r--meson_options.txt1
-rw-r--r--pyproject.toml10
-rw-r--r--python-package.nix41
-rw-r--r--src/build.c19
-rw-r--r--src/evanix-py.c14
-rw-r--r--src/evanix.c6
-rw-r--r--src/jobs.c48
-rw-r--r--src/queue.c1
12 files changed, 226 insertions, 67 deletions
diff --git a/flake.nix b/flake.nix
index 90992f3..ab78426 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,75 +3,99 @@
inputs.nixpkgs.url = "github:NixOs/nixpkgs/nixos-unstable";
- outputs = { self, nixpkgs }: let
- lib = nixpkgs.lib;
+ outputs =
+ { self, nixpkgs }:
+ let
+ lib = nixpkgs.lib;
- forSystem = f: system: f {
- inherit system;
- pkgs = import nixpkgs { inherit system; };
- };
+ forSystem =
+ f: system:
+ f {
+ inherit system;
+ pkgs = import nixpkgs { inherit system; };
+ };
- supportedSystems = lib.platforms.unix;
- forAllSystems = f: lib.genAttrs supportedSystems (forSystem f);
- in {
- devShells = forAllSystems ({ system, pkgs }: {
- default = pkgs.mkShell {
- name = "dev";
+ supportedSystems = lib.systems.flakeExposed;
+ forAllSystems = f: lib.genAttrs supportedSystems (forSystem f);
+ in
+ {
+ devShells = forAllSystems (
+ { system, pkgs }:
+ {
+ default = pkgs.mkShell {
+ name = "dev";
- buildInputs = with pkgs; [
- jq
- cjson
- nix-eval-jobs
+ buildInputs = with pkgs; [
+ jq
+ cjson
+ nix-eval-jobs
- pkg-config
- meson
- ninja
+ pkg-config
+ meson
+ ninja
- gdb
- ccls
- valgrind
- clang-tools # clang-format
- ];
+ gdb
+ ccls
+ valgrind
+ clang-tools # clang-format
+ ];
- shellHook = ''
- export PS1="\033[0;34m[󱄅 ]\033[0m $PS1"
- '';
- };
- });
+ shellHook = ''
+ export PS1="\033[0;34m[󱄅 ]\033[0m $PS1"
+ '';
+ };
+ }
+ );
- packages = forAllSystems ({ system, pkgs }: {
- evanix = pkgs.stdenv.mkDerivation (finalAttrs: {
- name = "evanix";
+ packages = forAllSystems (
+ { system, pkgs }:
+ {
+ default = self.packages.${system}.evanix;
+ evanix = pkgs.stdenv.mkDerivation (finalAttrs: {
+ name = "evanix";
- src = ./.;
- nativeBuildInputs = with pkgs; [
- meson
- ninja
- pkg-config
- makeWrapper
- ];
- buildInputs = with pkgs; [
- cjson
- nix-eval-jobs
- ];
+ src = ./.;
+ nativeBuildInputs = with pkgs; [
+ meson
+ ninja
+ pkg-config
+ makeWrapper
+ ];
+ buildInputs = with pkgs; [
+ cjson
+ nix-eval-jobs
+ ];
- postInstall = ''
- wrapProgram $out/bin/evanix \
- --prefix PATH : ${lib.makeBinPath [ pkgs.nix-eval-jobs ]}
- '';
+ postInstall = ''
+ wrapProgram $out/bin/evanix \
+ --prefix PATH : ${lib.makeBinPath [ pkgs.nix-eval-jobs ]}
+ '';
- meta = {
- homepage = "https://git.sinanmohd.com/evanix";
+ meta = {
+ homepage = "https://git.sinanmohd.com/evanix";
- license = lib.licenses.gpl3;
- platforms = supportedSystems;
- mainProgram = "evanix";
+ license = lib.licenses.gpl3;
+ platforms = supportedSystems;
+ mainProgram = "evanix";
- maintainers = with lib.maintainers; [ sinanmohd ];
- };
- });
+ maintainers = with lib.maintainers; [ sinanmohd ];
+ };
+ });
- default = self.packages.${system}.evanix;
- });
- };
+ evanix-py = pkgs.python3Packages.callPackage ./python-package.nix { };
+ pythonWithEvanix =
+ let
+ wrapper = pkgs.python3.withPackages (ps: [ (ps.callPackage ./python-package.nix { }) ]);
+ in
+ wrapper.overrideAttrs (oldAttrs: {
+ makeWrapperArgs = oldAttrs.makeWrapperArgs or [ ] ++ [
+ "--prefix"
+ "PATH"
+ ":"
+ "${lib.makeBinPath [ pkgs.nix-eval-jobs ]}"
+ ];
+ });
+ }
+ );
+ };
}
diff --git a/include/evanix.h b/include/evanix.h
index aa53b9f..c4285fc 100644
--- a/include/evanix.h
+++ b/include/evanix.h
@@ -7,6 +7,7 @@ struct evanix_opts_t {
bool isdryrun;
bool ispipelined;
bool close_stderr_exec;
+ char *system;
};
extern struct evanix_opts_t evanix_opts;
diff --git a/include/jobs.h b/include/jobs.h
index 11f6b01..37445c1 100644
--- a/include/jobs.h
+++ b/include/jobs.h
@@ -9,7 +9,7 @@ struct output {
};
struct job {
- char *name, *drv_path;
+ char *name, *drv_path, *attr;
bool transitive;
bool insubstituters;
@@ -32,6 +32,7 @@ typedef enum {
JOB_READ_EVAL_ERR = 2,
JOB_READ_JSON_INVAL = 3,
JOB_READ_CACHED = 4,
+ JOB_READ_SYS_MISMATCH = 5,
} job_read_state_t;
int job_read(FILE *stream, struct job **jobs);
diff --git a/meson.build b/meson.build
index 38f78d7..e5290f8 100644
--- a/meson.build
+++ b/meson.build
@@ -21,4 +21,13 @@ add_project_arguments(
cjson_dep = dependency('libcjson')
evanix_inc = include_directories('include')
+if get_option('build-python')
+ py = import('python').find_installation()
+ py.extension_module(
+ 'evanix',
+ 'src/evanix-py.c',
+ install: true,
+ )
+endif
+
subdir('src')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..e8baf64
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1 @@
+option('build-python', type: 'boolean', value: 'false')
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..b5a3375
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,10 @@
+[build-system]
+build-backend = 'mesonpy'
+requires = [ 'meson-python' ]
+
+[project]
+name = 'evanix'
+version = '0.0.1'
+
+[tool.meson-python.args]
+setup = [ '-Dbuild-python=true' ]
diff --git a/python-package.nix b/python-package.nix
new file mode 100644
index 0000000..a422052
--- /dev/null
+++ b/python-package.nix
@@ -0,0 +1,41 @@
+{
+ lib,
+ buildPythonPackage,
+ meson-python,
+ ninja,
+ pkg-config,
+ makeWrapper,
+ cjson,
+}:
+
+buildPythonPackage {
+ pname = "evanix";
+ version = "0.0.1";
+ pyproject = true;
+
+ src =
+ let
+ fs = lib.fileset;
+ in
+ fs.toSource {
+ root = ./.;
+ fileset = fs.unions [
+ ./src
+ ./include
+ ./meson.build
+ ./meson_options.txt
+ ./pyproject.toml
+ ];
+ };
+
+ build-system = [ meson-python ];
+ nativeBuildInputs = [
+ ninja
+ pkg-config
+ makeWrapper
+ ];
+ buildInputs = [
+ cjson
+ # nix-eval-jobs
+ ];
+}
diff --git a/src/build.c b/src/build.c
index 39750b5..87238e9 100644
--- a/src/build.c
+++ b/src/build.c
@@ -2,6 +2,7 @@
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <limits.h>
#include <string.h>
#include "build.h"
@@ -43,16 +44,29 @@ out:
static int build(struct queue *queue)
{
struct job *job;
- char *args[3];
+ char *args[5];
size_t argindex;
int ret;
+ char out_link[NAME_MAX] = "result";
+
ret = queue_pop(queue, &job, queue->htab);
if (ret < 0)
return ret;
+ if (job->attr) {
+ ret = snprintf(out_link, sizeof(out_link), "result-%s", job->attr);
+ if (ret < 0 || (size_t)ret > sizeof(out_link)) {
+ ret = -ENAMETOOLONG;
+ print_err("%s", strerror(-ret));
+ goto out_free_job;
+ }
+ }
+
argindex = 0;
args[argindex++] = "nix-build";
+ args[argindex++] = "--out-link";
+ args[argindex++] = out_link;
args[argindex++] = job->drv_path;
args[argindex++] = NULL;
@@ -64,9 +78,10 @@ static int build(struct queue *queue)
run("nix-build", args);
}
+out_free_job:
job_free(job);
- return 0;
+ return ret;
}
int build_thread_new(struct build_thread **build_thread, struct queue *q)
diff --git a/src/evanix-py.c b/src/evanix-py.c
new file mode 100644
index 0000000..c010e27
--- /dev/null
+++ b/src/evanix-py.c
@@ -0,0 +1,14 @@
+#include <Python.h>
+
+static PyMethodDef methods[] = {
+ {NULL, NULL, 0, NULL},
+};
+
+static struct PyModuleDef module = {
+ PyModuleDef_HEAD_INIT, "evanix", NULL, -1, methods,
+};
+
+PyMODINIT_FUNC PyInit_evanix(void)
+{
+ return PyModule_Create(&module);
+}
diff --git a/src/evanix.c b/src/evanix.c
index 64bd763..01279d1 100644
--- a/src/evanix.c
+++ b/src/evanix.c
@@ -14,6 +14,7 @@ static const char usage[] =
" -f, --flake Build a flake.\n"
" -d, --dry-run Show what derivations would be "
"built.\n"
+ " -s, --system System to build for."
" -p, --pipelined <bool> Use evanix build pipeline.\n"
" -c, --close-stderr-exec <bool> Close stderr on exec.\n"
"\n";
@@ -23,6 +24,7 @@ struct evanix_opts_t evanix_opts = {
.isflake = false,
.ispipelined = true,
.isdryrun = false,
+ .system = NULL,
};
static int evanix(char *expr);
@@ -99,6 +101,7 @@ int main(int argc, char *argv[])
{"help", no_argument, NULL, 'h'},
{"flake", no_argument, NULL, 'f'},
{"dry-run", no_argument, NULL, 'd'},
+ {"system", required_argument, NULL, 's'},
{"pipelined", required_argument, NULL, 'p'},
{"close-stderr-exec", required_argument, NULL, 'c'},
{NULL, 0, NULL, 0},
@@ -117,6 +120,9 @@ int main(int argc, char *argv[])
case 'd':
evanix_opts.isdryrun = true;
break;
+ case 's':
+ evanix_opts.system = optarg;
+ break;
case 'p':
ret = atob(optarg);
if (ret < 0) {
diff --git a/src/jobs.c b/src/jobs.c
index d303fed..4e3926a 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -11,7 +11,7 @@
#include "util.h"
static void output_free(struct output *output);
-static int job_new(struct job **j, char *name, char *drv_path,
+static int job_new(struct job **j, char *name, char *drv_path, char *attr,
struct job *parent);
static int job_output_insert(struct job *j, char *name, char *store_path);
static int job_read_inputdrvs(struct job *job, cJSON *input_drvs);
@@ -167,7 +167,7 @@ static int job_read_inputdrvs(struct job *job, cJSON *input_drvs)
int ret = 0;
for (cJSON *array = input_drvs; array != NULL; array = array->next) {
- ret = job_new(&dep_job, NULL, array->string, job);
+ ret = job_new(&dep_job, NULL, array->string, NULL, job);
if (ret < 0)
goto out_free_dep_job;
@@ -238,6 +238,7 @@ int job_read(FILE *stream, struct job **job)
char *drv_path = NULL;
struct job *j = NULL;
cJSON *root = NULL;
+ char *attr = NULL;
char *name = NULL;
int ret = 0;
@@ -253,6 +254,17 @@ int job_read(FILE *stream, struct job **job)
goto out_free;
}
+ temp = cJSON_GetObjectItemCaseSensitive(root, "system");
+ if (!cJSON_IsString(temp)) {
+ ret = JOB_READ_JSON_INVAL;
+ goto out_free;
+ }
+ if (evanix_opts.system != NULL &&
+ strcmp(evanix_opts.system, temp->valuestring)) {
+ ret = JOB_READ_SYS_MISMATCH;
+ goto out_free;
+ }
+
temp = cJSON_GetObjectItemCaseSensitive(root, "name");
if (!cJSON_IsString(temp)) {
ret = JOB_READ_JSON_INVAL;
@@ -260,6 +272,14 @@ int job_read(FILE *stream, struct job **job)
}
name = temp->valuestring;
+ temp = cJSON_GetObjectItemCaseSensitive(root, "attr");
+ if (!cJSON_IsString(temp)) {
+ ret = JOB_READ_JSON_INVAL;
+ goto out_free;
+ }
+ if (temp->valuestring[0] != '\0')
+ attr = temp->valuestring;
+
temp = cJSON_GetObjectItemCaseSensitive(root, "drvPath");
if (!cJSON_IsString(temp)) {
free(name);
@@ -268,7 +288,7 @@ int job_read(FILE *stream, struct job **job)
}
drv_path = temp->valuestring;
- ret = job_new(&j, name, drv_path, NULL);
+ ret = job_new(&j, name, drv_path, attr, NULL);
if (ret < 0)
goto out_free;
@@ -332,11 +352,12 @@ void job_free(struct job *job)
free(job->drv_path);
free(job->name);
+ free(job->attr);
free(job);
}
static int job_new(struct job **j, char *name, char *drv_path,
- struct job *parent)
+ char *attr, struct job *parent)
{
struct job *job;
int ret = 0;
@@ -360,12 +381,23 @@ static int job_new(struct job **j, char *name, char *drv_path,
job->parents_filled = 0;
job->parents = NULL;
+ if (attr != NULL) {
+ job->attr = strdup(attr);
+ if (job->attr == NULL) {
+ print_err("%s", strerror(errno));
+ ret = -errno;
+ goto out_free_job;
+ }
+ } else {
+ job->attr = NULL;
+ }
+
if (name != NULL) {
job->name = strdup(name);
if (job->name == NULL) {
print_err("%s", strerror(errno));
ret = -errno;
- goto out_free_job;
+ goto out_free_attr;
}
} else {
job->name = NULL;
@@ -390,6 +422,9 @@ out_free_drv_path:
out_free_name:
if (ret < 0)
free(job->name);
+out_free_attr:
+ if (ret < 0)
+ free(job->attr);
out_free_job:
if (ret < 0)
free(job);
@@ -402,12 +437,13 @@ out_free_job:
int jobs_init(FILE **stream, char *expr)
{
size_t argindex;
- char *args[5];
+ char *args[6];
int ret;
argindex = 0;
args[argindex++] = "nix-eval-jobs";
args[argindex++] = "--check-cache-status";
+ args[argindex++] = "--force-recurse";
if (evanix_opts.isflake)
args[argindex++] = "--flake";
args[argindex++] = expr;
diff --git a/src/queue.c b/src/queue.c
index a5b4d6a..09eebb6 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -67,6 +67,7 @@ void *queue_thread_entry(void *queue_thread)
break;
} else if (ret == JOB_READ_EVAL_ERR ||
ret == JOB_READ_JSON_INVAL ||
+ ret == JOB_READ_SYS_MISMATCH ||
ret == JOB_READ_CACHED) {
continue;
} else if (ret == JOB_READ_SUCCESS) {