on master help sign in
Revert "Revert "Get all languages working in prybar with Nix""

This reverts commit e521913e538ce8c119820ea21c4b3c46b6960b2b.

commit340845d9f68c39e512b5305c8ff2ed5b791afc4d authorguillaume <guillaume@repl.it> dateWed 23 Jun 2021, 16:47 (5 years ago) parente521913
16 files changed+267−150
build-prybar.nix+43−4 default.nix+58−35 languages/R/main.go+1−1 languages/clojure/deps.nix+65 languages/clojure/main.go+3−3 languages/clojure/wrappedClojure.nix+18 languages/julia/julia.nix+26 languages/nodejs/main.go+1−1 languages/ocaml/main.go+11−2 languages/ruby/main.go+1−1 languages/spidermonkey/main.go−90 run_tests_language+28 tests/clojure/run_code.exp+1−2 tests/julia/header.exp+2−2 tests/nodejs/err.exp+9−9 tests/tcl/1_plus_1.exp → tests/tcl/1_plus_1.exp_skip
build-prybar.nix+43−4
@@ -1,13 +1,20 @@
1−{ language, buildInputs ? [] }:
1+{ language, buildInputs ? [], binaries ? [], setFlags ? false, pkgName ? language, versionArg ? "" }:
22
3−{ lib, buildGoModule, fetchFromGitHub, bash, pkg-config, runCommand, git, copyPathToStore }:
3+{ lib, buildGoModule, fetchFromGitHub, bash, expect, pkg-config, runCommand, git, python3, copyPathToStore }:
44
55let
66 src = copyPathToStore ./.;
77 revision = runCommand "get-rev" {
8− nativeBuildInputs = [ git ];
8+ nativeBuildInputs = [ git python3 ];
99 dummy = builtins.currentTime;
10− } "GIT_DIR=${src}/.git git rev-parse --short HEAD | tr -d '\n' > $out";
10+ } ''
11+ if [ -d ${src}/.git ]; then
12+ cd ${src}
13+ git rev-parse --short HEAD | tr -d '\n' > $out
14+ else
15+ echo ${versionArg} | tr -d '\n' > $out
16+ fi
17+ '';
1118in buildGoModule {
1219 pname = "prybar-${language}";
1320 version = builtins.readFile revision;
@@ -21,11 +28,43 @@ in buildGoModule {
2128
2229 vendorSha256 = null;
2330
31+ # This prebiuild hook will setup the compiler flags on demand based on the package
32+ # If a language requires this, it MUST expost a ${pkgName}.pc file in its `lib/pkg-config`
33+ # for pkg-config to detect it. Otherwise, we can't find the required flags.
2434 preBuild = ''
35+ ${if setFlags then ''
36+ NIX_CFLAGS_COMPILE="$(pkg-config --cflags ${pkgName}) $NIX_CFLAGS_COMPILE"
37+ NIX_LDFLAGS="$(pkg-config --libs-only-L ${pkgName}) $(pkg-config --libs-only-l ${pkgName}) $NIX_LDFLAGS"
38+ '' else ""}
39+
2540 ${bash}/bin/bash ./scripts/inject.sh ${language}
2641 go generate ./languages/${language}/main.go
2742 '';
2843
44+ # The test file expect the binary to be in the current directory rather than bin
45+ preCheck = ''
46+ cp $GOPATH/bin/${language} ./prybar-${language}
47+ ln -s ${expect} /usr
48+ '';
49+
50+ # Add all the dependencies to the check. Binaries should include the language interpreter/binaries
51+ # for testing the language.
52+ checkInputs = [ expect ] ++ buildInputs ++ binaries;
53+
54+ # Run the end-to-end tests for this specific language
55+ checkPhase = ''
56+ runHook preCheck
57+
58+ ${bash}/bin/bash ./run_tests_language ${language}
59+
60+ runHook postCheck
61+ '';
62+
63+ # Delete the test binary we copied in the preCheck
64+ postCheck = ''
65+ rm -f ./prybar-${language}
66+ '';
67+
2968 postInstall = ''
3069 mv $out/bin/${language} $out/bin/prybar-${language}
3170 '';
default.nix+58−35
@@ -1,40 +1,63 @@
1−{ pkgs ? import <nixpkgs>{} } :
1+{ pkgs ? import <nixpkgs>{}, versionArg ? "" } :
22let
33 buildPrybar = attrs: pkgs.callPackage(import ./build-prybar.nix attrs) {};
4+
5+ julia = import ./languages/julia/julia.nix { inherit pkgs; };
6+ clojureWithCP = import ./languages/clojure/wrappedClojure.nix { inherit pkgs; };
47in
58{
6− # TODO: These don't quite work yet
7−
8− # Won't build
9− # prybar-R = buildPrybar { language = "R"; buildInputs = [ pkgs.R ]; };
10−
11− # Julia 1.1 doesn't seem to be on nix
12− # prybar-julia = buildPrybar { language = "julia"; buildInputs = [ julia_13 ]; };
13−
14− # Has problem reading from prybar_assets. Seems like a bug with the impl.
15− # prybar-nodejs = buildPrybar { language = "nodejs"; buildInputs = [ ]; };
16−
17− # Ruby 2.5 is deprecated!
18− # prybar-ruby = buildPrybar { language = "ruby"; buildInputs = [ ruby_2_5 ]; };
19−
20− # Untested, spidermonkey not supported on darwin. Feel free to test on linux.
21− # prybar-spidermonkey = buildPrybar { language = "spidermonkey"; buildInputs = [ spidermonkey ]; };
22−
23− prybar-python2 = buildPrybar { language = "python2"; buildInputs = [ pkgs.python2 ]; };
24−
25− prybar-python3 = buildPrybar { language = "python3"; buildInputs = [ pkgs.python3 ]; };
26−
27− prybar-lua = buildPrybar { language = "lua"; buildInputs = [ pkgs.lua5_1 pkgs.readline ]; };
28−
29− prybar-clojure = buildPrybar { language = "clojure"; buildInputs = [ pkgs.clojure ]; };
30−
31− prybar-elisp = buildPrybar { language = "elisp"; };
32−
33− prybar-ocaml = buildPrybar { language = "ocaml"; };
34−
35− prybar-scala = buildPrybar { language = "scala"; };
36−
37− prybar-sqlite = buildPrybar { language = "sqlite"; };
38−
39− prybar-tcl = buildPrybar { language = "tcl"; buildInputs = [ pkgs.tcl ]; };
9+ prybar-R = buildPrybar {
10+ language = "R";
11+ buildInputs = [ pkgs.R ];
12+ versionArg = versionArg;
13+ pkgName = "libR";
14+ setFlags = true;
15+ };
16+
17+ prybar-julia = buildPrybar {
18+ language = "julia";
19+ buildInputs = [ julia ];
20+ versionArg = versionArg;
21+ setFlags = true;
22+ };
23+
24+ prybar-nodejs = buildPrybar { language = "nodejs"; binaries = [ pkgs.nodejs ]; versionArg = versionArg; };
25+
26+ # The official Ruby packages is running ruby 2.7
27+ prybar-ruby = buildPrybar {
28+ language = "ruby";
29+ buildInputs = [ pkgs.ruby ];
30+ pkgName = "ruby-2.7";
31+ versionArg = versionArg;
32+ setFlags = true;
33+ };
34+
35+ prybar-python2 = buildPrybar { language = "python2"; buildInputs = [ pkgs.python2 ]; versionArg = versionArg; };
36+
37+ prybar-python3 = buildPrybar { language = "python3"; buildInputs = [ pkgs.python3 ]; versionArg = versionArg; };
38+
39+ prybar-lua = buildPrybar { language = "lua"; buildInputs = [ pkgs.lua5_1 pkgs.readline ]; versionArg = versionArg; };
40+
41+ prybar-clojure = buildPrybar {
42+ language = "clojure";
43+ buildInputs = [ clojureWithCP ];
44+ binaries = [ pkgs.jdk11_headless ];
45+ versionArg = versionArg;
46+ };
47+
48+ prybar-elisp = buildPrybar { language = "elisp"; versionArg = versionArg; };
49+
50+ prybar-ocaml = buildPrybar {
51+ language = "ocaml";
52+ # This has to be in the build inputs so it set-ups the library paths before the check phase
53+ # It will not be copied over to the final package.
54+ buildInputs = [ pkgs.opam pkgs.ocaml pkgs.ocamlPackages.findlib pkgs.ocamlPackages.topkg pkgs.ocamlPackages.reason ];
55+ versionArg = versionArg;
56+ };
57+
58+ prybar-scala = buildPrybar { language = "scala"; versionArg = versionArg; };
59+
60+ prybar-sqlite = buildPrybar { language = "sqlite"; binaries = [ pkgs.sqlite ]; versionArg = versionArg; };
61+
62+ prybar-tcl = buildPrybar { language = "tcl"; buildInputs = [ pkgs.tcl ]; versionArg = versionArg; };
4063}
languages/R/main.go+1−1
@@ -6,7 +6,7 @@ package main
66#cgo pkg-config: libR
77#include <stdlib.h>
88#include <Rembedded.h>
9−#include <RVersion.h>
9+#include <Rversion.h>
1010#include <Rinternals.h>
1111#include <R_ext/Parse.h>
1212#include <Rembedded.h>
languages/clojure/deps.nixnew file+65
@@ -0,0 +1,65 @@
1+# generated by clj2nix-1.0.6
2+{ pkgs ? import <nixpkgs> {} }:
3+
4+let repos = [
5+ "http://jcenter.bintray.com"
6+ "https://repo1.maven.org/maven2/"
7+ "https://repo.clojars.org/" ];
8+
9+ in rec {
10+ makePaths = {extraClasspaths ? null}:
11+ (pkgs.lib.concatMap
12+ (dep:
13+ builtins.map
14+ (path:
15+ if builtins.isString path then
16+ path
17+ else if builtins.hasAttr "jar" path then
18+ path.jar
19+ else if builtins.hasAttr "outPath" path then
20+ path.outPath
21+ else
22+ path
23+ )
24+ dep.paths)
25+ packages)
26+ ++ (if extraClasspaths != null then [ extraClasspaths ] else []);
27+ makeClasspaths = {extraClasspaths ? null}: builtins.concatStringsSep ":" (makePaths {inherit extraClasspaths;});
28+ packageSources = builtins.map (dep: dep.src) packages;
29+
30+ packages = [
31+ rec {
32+ name = "clojure/org.clojure";
33+ src = pkgs.fetchMavenArtifact {
34+ inherit repos;
35+ artifactId = "clojure";
36+ groupId = "org.clojure";
37+ sha512 = "4bb567b9262d998f554f44e677a8628b96e919bc8bcfb28ab2e80d9810f8adf8f13a8898142425d92f3515e58c57b16782cff12ba1b5ffb38b7d0ccd13d99bbc";
38+ version = "1.10.3";
39+ };
40+ paths = [ src ];
41+ }
42+ rec {
43+ name = "spec.alpha/org.clojure";
44+ src = pkgs.fetchMavenArtifact {
45+ inherit repos;
46+ artifactId = "spec.alpha";
47+ groupId = "org.clojure";
48+ sha512 = "0740dc3a755530f52e32d27139a9ebfd7cbdb8d4351c820de8d510fe2d52a98acd6e4dfc004566ede3d426e52ec98accdca1156965218f269e60dd1cd4242a73";
49+ version = "0.2.194";
50+ };
51+ paths = [ src ];
52+ }
53+ rec {
54+ name = "core.specs.alpha/org.clojure";
55+ src = pkgs.fetchMavenArtifact {
56+ inherit repos;
57+ artifactId = "core.specs.alpha";
58+ groupId = "org.clojure";
59+ sha512 = "c1d2a740963896d97cd6b9a8c3dcdcc84459ea66b44170c05b8923e5fbb731b4b292b217ed3447bbc9e744c9a496552f77a6c38aea232e5e69f8faa627dea4b5";
60+ version = "0.2.56";
61+ };
62+ paths = [ src ];
63+ }
64+ ];
65+}
languages/clojure/main.go+3−3
@@ -1,6 +1,6 @@
11package main
22
3−//go:generate ../../scripts/gofiles.sh generated_files.go
3+//go:generate bash ../../scripts/gofiles.sh generated_files.go
44
55import (
66 "fmt"
@@ -35,14 +35,14 @@ func findHelper(path string) string {
3535}
3636
3737func Execute(config *utils.Config) {
38− path, err := exec.LookPath("clj")
38+ path, err := exec.LookPath("clojure")
3939
4040 if err != nil {
4141 panic(err)
4242 }
4343
4444 env := os.Environ()
45− args := []string{"clj"}
45+ args := []string{"clojure"}
4646
4747 hasOption := config.Code != "" || config.Exp != "" ||
4848 config.Interactive || config.OurInteractive
languages/clojure/wrappedClojure.nixnew file+18
@@ -0,0 +1,18 @@
1+{ pkgs }:
2+
3+let
4+ cljdeps = import ./deps.nix { inherit pkgs; };
5+ classp = cljdeps.makeClasspaths {};
6+in pkgs.stdenv.mkDerivation {
7+ name = "wrapped-clojure-with-deps";
8+
9+ src = ./.;
10+ nativeBuildInputs = [ pkgs.makeWrapper ];
11+ buildInputs = [ pkgs.clojure ];
12+
13+ installPhase = ''
14+ mkdir -p $out/bin
15+
16+ makeWrapper ${pkgs.clojure}/bin/clojure $out/bin/clojure --add-flags "-Scp ${builtins.toString classp}"
17+ '';
18+}
languages/julia/julia.nixnew file+26
@@ -0,0 +1,26 @@
1+{ pkgs }:
2+
3+pkgs.stdenv.mkDerivation rec {
4+ pname = "julia-sources";
5+ version = "1.5.4";
6+
7+ src = {
8+ x86_64-linux = pkgs.fetchurl {
9+ url = "https://julialang-s3.julialang.org/bin/linux/x64/${pkgs.lib.versions.majorMinor version}/julia-${version}-linux-x86_64.tar.gz";
10+ sha256 = "1icb3rpn2qs6c3rqfb5rzby1pj6h90d9fdi62nnyi4x5s58w7pl0";
11+ };
12+ }.${pkgs.stdenv.hostPlatform.system} or (throw "Unsupported system: ${pkgs.stdenv.hostPlatform.system}");
13+
14+ installPhase = ''
15+ cp -r . $out
16+
17+ mkdir $out/lib/pkgconfig
18+ cat > $out/lib/pkgconfig/julia.pc <<- EOM
19+ Name: julia
20+ Cflags: -I$out/include/julia
21+ Version: 1.5.4
22+ Description: it's julia
23+ Libs: -L$out\/lib -ljulia
24+ EOM
25+ '';
26+}
languages/nodejs/main.go+1−1
@@ -1,6 +1,6 @@
11package main
22
3−//go:generate ../../scripts/gofiles.sh generated_files.go
3+//go:generate bash ../../scripts/gofiles.sh generated_files.go
44
55import (
66 "io/ioutil"
languages/ocaml/main.go+11−2
@@ -1,13 +1,14 @@
11// OCaml main
22package main
33
4−//go:generate ../../scripts/gofiles.sh generated_files.go
4+//go:generate bash ../../scripts/gofiles.sh generated_files.go
55
66import (
77 "github.com/replit/prybar/utils"
88 "io/ioutil"
99 "os"
1010 "os/exec"
11+ "strings"
1112 "syscall"
1213)
1314
@@ -40,8 +41,16 @@ func Execute(config *utils.Config) {
4041 panic(err)
4142 }
4243
44+ args := []string{"ocaml"}
45+ // Fix for getting the various libs added to prybar when running through nix
46+ if value, ok := os.LookupEnv("OCAMLPATH"); ok {
47+ for _, val := range strings.Split(value, ":") {
48+ args = append(args, "-I", val)
49+ }
50+ }
51+
4352 env := os.Environ()
44− args := []string{"ocaml", findHelper("repl"), "-s", "ml"}
53+ args = append(args, findHelper("repl"), "-s", "ml")
4554
4655 if config.Quiet {
4756 args = append(args, "-q")
languages/ruby/main.go+1−1
@@ -3,7 +3,7 @@ package main
33// USING_CGO
44
55/*
6−#cgo pkg-config: ruby-2.5
6+#cgo CGO_LDFLAGS_ALLOW="-Wl,--compress-debug-sections=zlib" pkg-config: --libs --cflags ruby-2.7
77#include "pry_ruby.h"
88*/
99import "C"
languages/spidermonkey/main.godeleted−90
@@ -1,90 +0,0 @@
1−package main
2−
3−// USING_CGO
4−
5−/*
6−#cgo pkg-config: mozjs185
7−#include "jsapi.h"
8−
9−static JSClass global_class = {
10− "global", JSCLASS_GLOBAL_FLAGS,
11− JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
12− JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
13− JSCLASS_NO_OPTIONAL_MEMBERS
14−};
15−
16−JSRuntime *rt;
17−JSContext *cx;
18−JSObject *global;
19−
20−int pry_open() {
21−
22−
23− rt = JS_NewRuntime(8 * 1024 * 1024);
24− if (rt == NULL) return 1;
25−
26− cx = JS_NewContext(rt, 8192);
27− if (cx == NULL) return 1;
28−
29− JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
30− JS_SetVersion(cx, JSVERSION_LATEST);
31− //JS_SetErrorReporter(cx, reportError);
32−
33−
34− global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
35− if (global == NULL) return 1;
36−
37−
38− if (!JS_InitStandardClasses(cx, global)) return 1;
39− return 0;
40−}
41−
42−int pry_eval(const char* script) {
43− jsval rval;
44− JSString *str;
45− JSBool ok;
46− const char *filename = "noname";
47− uintN lineno = 0;
48−
49− ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno, &rval);
50− if (rval == JS_FALSE)
51− return 1;
52−
53− str = JS_ValueToString(cx, rval);
54− printf("%s\n", JS_EncodeString(cx, str));
55−}
56−
57−void pry_close() {
58− JS_DestroyContext(cx);
59− JS_DestroyRuntime(rt);
60− JS_ShutDown();
61−}
62−
63−*/
64−import "C"
65−
66−import (
67− "unsafe"
68−)
69−
70−type SpiderMonkey struct{}
71−
72−func (p SpiderMonkey) Open() {
73− C.pry_open()
74−}
75−
76−func (p SpiderMonkey) Version() string {
77− return C.GoString(C.JS_GetImplementationVersion())
78−}
79−
80−func (p SpiderMonkey) Eval(code string) {
81− ccode := C.CString(code)
82− defer C.free(unsafe.Pointer(ccode))
83− C.pry_eval(ccode)
84−}
85−
86−func (p SpiderMonkey) Close() {
87− C.pry_close()
88−}
89−
90−var Instance = SpiderMonkey{}
run_tests_languagenew file+28
@@ -0,0 +1,28 @@
1+#!/usr/bin/env bash
2+
3+stty cols 80
4+stty rows 20
5+
6+language=$1
7+tests=$(find "./tests/${language}" -printf '%P\n')
8+
9+for t in ${tests}; do
10+ if [[ $t != *.exp ]]; then
11+ echo "$t:"
12+ continue
13+ fi
14+
15+ name=$(echo -n $t | sed -s 's/.*\/\(.*\).exp/\1/' | sed -s 's/_/ /g')
16+
17+ echo -n "... ${language} $name"
18+
19+ test_out=$(timeout 15 "./tests/${language}/$t" 2>&1)
20+ if [[ $? != 0 ]]; then
21+ echo -e "\n========== \"$t\" failed =========="
22+ echo "$test_out"
23+ exit 1;
24+ fi
25+
26+ echo -ne '\r'
27+ echo -e " \e[32m✓\e[0m $name"
28+done
tests/clojure/run_code.exp+1−2
@@ -1,8 +1,7 @@
11#!/usr/bin/expect -f
22
33set timeout -1
4−spawn ./prybar-clojure -c {(do (println "foo") "bar")}
4+spawn ./prybar-clojure -q -c {(do (println "foo") "bar")}
55match_max 100000
66expect -re "^\r\r\u001b\\\[K\rfoo\r\r\n$"
7−expect eof
87
tests/julia/header.exp+2−2
@@ -43,14 +43,14 @@ if {$force_conservative} {
4343
4444
4545set timeout -1
46−spawn prybar-julia -i
46+spawn ./prybar-julia -i
4747match_max 100000
4848expect -exact " \[1m\[32m_\[0m\r
4949 \[1m\[34m_\[0m \[0m_\[0m \[1m\[31m_\[1m\[32m(_)\[1m\[35m_\[0m | Documentation: https://docs.julialang.org\r
5050 \[1m\[34m(_)\[0m | \[1m\[31m(_)\[0m \[1m\[35m(_)\[0m |\r
5151 \[0m_ _ _| |_ __ _\[0m | Type \"?\" for help, \"\]?\" for Pkg help.\r
5252 \[0m| | | | | | |/ _` |\[0m |\r
53− \[0m| | |_| | | | (_| |\[0m | Version 1.4.1 (2020-04-14)\r
53+ \[0m| | |_| | | | (_| |\[0m | Version 1.5.4 (2021-03-11)\r
5454 \[0m_/ |\\__'_|_|_|\\__'_|\[0m | Official https://julialang.org/ release\r
5555\[0m|__/\[0m |\r
5656\r
tests/nodejs/err.exp+9−9
@@ -8,14 +8,14 @@ send -- "x\r"
88expect -exact "x\r\r
99\[0m\[31mReferenceError: x is not defined\r
1010 at REPL1:1:1\r
11− at Script.runInThisContext (vm.js:120:18)\r
12− at REPLServer.defaultEval (repl.js:442:29)\r
13− at bound (domain.js:427:14)\r
14− at REPLServer.runBound \[as eval\] (domain.js:440:12)\r
15− at REPLServer.onLine (repl.js:777:10)\r
16− at REPLServer.emit (events.js:314:20)\r
17− at REPLServer.EventEmitter.emit (domain.js:483:12)\r
18− at REPLServer.Interface._onLine (readline.js:329:10)\r
19− at REPLServer.Interface._line (readline.js:658:8)\[0m\[1G\[0J--> \[5G"
11+ at Script.runInThisContext (vm.js:133:18)\r
12+ at REPLServer.defaultEval (repl.js:486:29)\r
13+ at bound (domain.js:416:15)\r
14+ at REPLServer.runBound \[as eval\] (domain.js:427:12)\r
15+ at REPLServer.onLine (repl.js:819:10)\r
16+ at REPLServer.emit (events.js:376:20)\r
17+ at REPLServer.emit (domain.js:470:12)\r
18+ at REPLServer.Interface._onLine (readline.js:342:10)\r
19+ at REPLServer.Interface._line (readline.js:671:8)\[0m\[1G\[0J--> \[5G"
2020send -- ""
2121expect eof
tests/tcl/1_plus_1.exp → tests/tcl/1_plus_1.exp_skiprenamed

The content is the same.