emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* How to use mpirun with C or C++ Org-babel?
@ 2023-12-07 23:10 Edgar Lux
  2023-12-08 10:36 ` tbanelwebmin
  0 siblings, 1 reply; 11+ messages in thread
From: Edgar Lux @ 2023-12-07 23:10 UTC (permalink / raw)
  To: Emacs Orgmode

Hello, I found [1][2] that it is possible to change the compiler for C and C++ source blocks. I would like to know if there is a way to add =mpirun -np 2= (where 2 can be any other number) to run the resulting executable. Thanks!


[1] https://orgmode.org/worg//org-contrib/babel/languages/ob-doc-C.html
[2] https://github.com/gheber/literate-hdf5

-- 
Sent with https://mailfence.com  
Secure and private email


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-07 23:10 How to use mpirun with C or C++ Org-babel? Edgar Lux
@ 2023-12-08 10:36 ` tbanelwebmin
  2023-12-08 15:47   ` Leo Butler
  0 siblings, 1 reply; 11+ messages in thread
From: tbanelwebmin @ 2023-12-08 10:36 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/html, Size: 2491 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-08 10:36 ` tbanelwebmin
@ 2023-12-08 15:47   ` Leo Butler
  2023-12-08 22:24     ` Ihor Radchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Leo Butler @ 2023-12-08 15:47 UTC (permalink / raw)
  To: tbanelwebmin; +Cc: emacs-orgmode@gnu.org

On Fri, Dec 08 2023, tbanelwebmin <tbanelwebmin@free.fr> wrote:

> Caution: This message was sent from outside the University of Manitoba.
>
> On 23-12-08 00:10, Edgar Lux wrote:
>
>     Hello, I found [1][2] that it is possible to change the compiler for C and C++
>     source blocks. I would like to know if there is a way to add =mpirun -np 2=
>     (where 2 can be any other number) to run the resulting executable. Thanks! [1] 
>     https://orgmode.org/worg//org-contrib/babel/languages/ob-doc-C.html [2] 
>     https://github.com/gheber/literate-hdf5
>
> I guess you want to run the executable after it has been compiled, with a command
> like this one:
>
> mpirun -np 2 /tmp/babel-ad2pdk/C-bin-JTvjS4
>
> Currently it is not possible.
>
> There is the :cmdline specifier which adds parameters to the executable, like this:
>
> #+begin_src C++ :cmdline AAA BBB CCC
> int main (int nargs, char** argv)
> {
>    // argv will be {
>    //   "/tmp/babel-ad2pdk/C-bin-JTvjS4",
>    //   "AAA",
>    //   "BBB",
>    //   "CCC"
>    // }
> }
> #+end_src
>
> Those parameters come AFTER the executable, whereas mpirun should come BEFORE the
> executable.
>
> An extension may be written in ob-C.el, in the org-babel-C-execute function.
> The relevant line is:
>   (concat tmp-bin-file cmdline)
>
> If you want to contribute...

If you are wanting to run jobs with mpirun, then I will guess that they
are relatively long-running. However, ob-C.el does not support
asynchronous (background) execution, so your emacs would be tied up for
the duration. I doubt you want that.

I submitted an imperfect patch some time ago [1] that targeted your use
case: allow ob-C.el to create a named binary. Unfortunately, Ihor
dropped the issue due to lack of interest from other users.

My goal was to enable something like this to work:

#+begin_src cpp :includes <iostream> :results none :file ./hello-world
std::cout << "Hello World!\n";
#+end_src

#+begin_src bash :async t
mpirun -np 4 ./hello-world
#+end_src

As I said, the patch I wrote was not perfect, but I am happy to re-visit
the issue. The ability to create named binaries would significantly
increase the usability of ob-C for projects where you want to compile
the source once and run the binary repeatedly for potentially long
periods of time.

Leo

[1] https://list.orgmode.org/87fs81egk5.fsf@t14.reltub.ca/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-08 15:47   ` Leo Butler
@ 2023-12-08 22:24     ` Ihor Radchenko
  2023-12-13 16:09       ` Leo Butler
  0 siblings, 1 reply; 11+ messages in thread
From: Ihor Radchenko @ 2023-12-08 22:24 UTC (permalink / raw)
  To: Leo Butler; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

> I submitted an imperfect patch some time ago [1] that targeted your use
> case: allow ob-C.el to create a named binary. Unfortunately, Ihor
> dropped the issue due to lack of interest from other users.
>
> My goal was to enable something like this to work:
>
> #+begin_src cpp :includes <iostream> :results none :file ./hello-world
> std::cout << "Hello World!\n";
> #+end_src
>
> #+begin_src bash :async t
> mpirun -np 4 ./hello-world
> #+end_src
>
> As I said, the patch I wrote was not perfect, but I am happy to re-visit
> the issue. The ability to create named binaries would significantly
> increase the usability of ob-C for projects where you want to compile
> the source once and run the binary repeatedly for potentially long
> periods of time.

Note that I did not oppose the above behaviour when the result of
evaluation is just compiling to :file. The problem was with compiling to
a :file and _also_ executing it.

If you want to propose a patch that will allow compile-only, I see no
problem at all.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-08 22:24     ` Ihor Radchenko
@ 2023-12-13 16:09       ` Leo Butler
  2023-12-14 14:08         ` Ihor Radchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Leo Butler @ 2023-12-13 16:09 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 672 bytes --]

On Fri, Dec 08 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> I submitted an imperfect patch some time ago [1] that targeted your use
>> case: allow ob-C.el to create a named binary.

> Note that I did not oppose the above behaviour when the result of
> evaluation is just compiling to :file. The problem was with compiling to
> a :file and _also_ executing it.
>
> If you want to propose a patch that will allow compile-only, I see no
> problem at all.

Ok, thank you for the clarification. I had gone on holidays after you
put up the poll and lost track.

Please see the attached patch.

Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-C.el-add-compile-only-header-to-compile-to-a.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-C.el-add-compile-only-header-to-compile-to-a.patch", Size: 8800 bytes --]

From 7d8e406bc4a92e2e2eab772b2671dcd72ca8c202 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 12 Dec 2023 12:32:41 -0600
Subject: [PATCH] lisp/ob-C.el: add :compile-only header to compile to a named
 target

* lisp/ob-C.el (org-babel-C-execute): The new header argument,
`:compile-only', causes source and compiled binary files to be named
using the `:file' header argument.  When `:compile-only' is set,
execution of source block ends at compilation.  The naming of source
and binary filenames is factored out to `org-babel-C-src/bin-file'.
* lisp/ob-C.el (org-babel-C-src/bin-file): A new function that factors
out the setting of source and binary filenames.  It also signals an
error if `:compile-only' is set, but `:file' is not.
* testing/examples/ob-C-test.org: Add three example that exercise the
`:compile-only' header argument, including one that causes an error.
* testing/lisp/test-ob-C.el: Add three tests of the `:compile-only'
header argument.  New tests: ob-C/set-src+bin-file-name-{1,2,3}.

Refs: https://list.orgmode.org/87fs81egk5.fsf@t14.reltub.ca/
https://list.orgmode.org/87msukbadu.fsf@localhost/
---
 lisp/ob-C.el                   | 83 ++++++++++++++++++++--------------
 testing/examples/ob-C-test.org | 26 +++++++++++
 testing/lisp/test-ob-C.el      | 32 +++++++++++++
 3 files changed, 108 insertions(+), 33 deletions(-)

diff --git a/lisp/ob-C.el b/lisp/ob-C.el
index 0278fc02a..dd772dc97 100644
--- a/lisp/ob-C.el
+++ b/lisp/ob-C.el
@@ -53,7 +53,8 @@
 				    (main    . :any)
 				    (flags   . :any)
 				    (cmdline . :any)
-				    (libs    . :any))
+				    (libs    . :any)
+                                    (compile-only . (nil no t yes)))
   "C/C++-specific header arguments.")
 
 (defconst org-babel-header-args:C++
@@ -128,17 +129,32 @@ This function is called by `org-babel-execute-src-block'."
   "Expand C BODY according to its header arguments PARAMS."
   (let ((org-babel-c-variant 'c)) (org-babel-C-expand-C body params)))
 
+(defun org-babel-C-src/bin-file (params src? compile-only?)
+  "Return the src or bin filename to `org-babel-C-execute'.
+
+If `SRC?' is T, a file extension is added to the filename.  By
+default, the filename is created by `org-babel-temp-file'. If
+`COMPILE-ONLY?' is T, the filename is taken from the `:file'
+field in `PARAMS'; if that is NIL, an error occurs."
+  (let ((f (cdr (assq :file params))))
+    (when (and compile-only? (null f))
+      (error "Error: When COMPILE-ONLY is T or YES, output FILE needs to be set"))
+    (let* ((file (cond (compile-only? f) (src? "C-src-") (t "C-bin-")))
+           (ext (if src? (pcase org-babel-c-variant
+	                   (`c ".c") (`cpp ".cpp") (`d ".d"))
+                  org-babel-exeext)))
+      (org-babel-process-file-name
+       (if compile-only? (concat file ext)
+         (org-babel-temp-file file ext))))))
+
 (defun org-babel-C-execute (body params)
   "Execute C/C++/D BODY according to its header arguments PARAMS.
 This function should only be called by `org-babel-execute:C' or
 `org-babel-execute:C++' or `org-babel-execute:D'."
-  (let* ((tmp-src-file (org-babel-temp-file
-			"C-src-"
-			(pcase org-babel-c-variant
-			  (`c ".c") (`cpp ".cpp") (`d ".d"))))
-	 (tmp-bin-file			;not used for D
-	  (org-babel-process-file-name
-	   (org-babel-temp-file "C-bin-" org-babel-exeext)))
+  (let* ((compile-only? (let ((c (cdr (assq :compile-only params))))
+                          (or (string= c "t") (string= c "yes"))))
+         (tmp-src-file (org-babel-C-src/bin-file params t compile-only?))
+	 (tmp-bin-file (org-babel-C-src/bin-file params nil compile-only?)) ;not used for D
 	 (cmdline (cdr (assq :cmdline params)))
 	 (cmdline (if cmdline (concat " " cmdline) ""))
 	 (flags (cdr (assq :flags params)))
@@ -170,31 +186,32 @@ This function should only be called by `org-babel-execute:C' or
 		libs)
 	""))
       (`d nil)) ;; no separate compilation for D
-    (let ((results
-	   (org-babel-eval
-	    (pcase org-babel-c-variant
-	      ((or `c `cpp)
-	       (concat tmp-bin-file cmdline))
-	      (`d
-	       (format "%s %s %s %s"
-		       org-babel-D-compiler
-		       flags
-		       (org-babel-process-file-name tmp-src-file)
-		       cmdline)))
-	    "")))
-      (when results
-	(setq results (org-remove-indentation results))
-	(org-babel-reassemble-table
-	 (org-babel-result-cond (cdr (assq :result-params params))
-	   results
-	   (let ((tmp-file (org-babel-temp-file "c-")))
-	     (with-temp-file tmp-file (insert results))
-	     (org-babel-import-elisp-from-file tmp-file)))
-	 (org-babel-pick-name
-	  (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
-	 (org-babel-pick-name
-	  (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))
-      )))
+    (unless compile-only?
+      (let ((results
+	     (org-babel-eval
+	      (pcase org-babel-c-variant
+	        ((or `c `cpp)
+	         (concat tmp-bin-file cmdline))
+	        (`d
+	         (format "%s %s %s %s"
+		         org-babel-D-compiler
+		         flags
+		         (org-babel-process-file-name tmp-src-file)
+		         cmdline)))
+	      "")))
+        (when results
+	  (setq results (org-remove-indentation results))
+	  (org-babel-reassemble-table
+	   (org-babel-result-cond (cdr (assq :result-params params))
+	     results
+	     (let ((tmp-file (org-babel-temp-file "c-")))
+	       (with-temp-file tmp-file (insert results))
+	       (org-babel-import-elisp-from-file tmp-file)))
+	   (org-babel-pick-name
+	    (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+	   (org-babel-pick-name
+	    (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))
+        ))))
 
 (defun org-babel-C-expand-C++ (body params)
   "Expand C/C++ BODY with according to its header arguments PARAMS."
diff --git a/testing/examples/ob-C-test.org b/testing/examples/ob-C-test.org
index c7a96f665..f636aabe8 100644
--- a/testing/examples/ob-C-test.org
+++ b/testing/examples/ob-C-test.org
@@ -174,3 +174,29 @@ std::cout << "\"line 1\"\n";
 std::cout << "\"line 2\"\n";
 std::cout << "\"line 3\"\n";
 #+end_src
+
+* File naming
+:PROPERTIES:
+:ID:       1a691f36-f9c1-4531-8fc0-ee7b21ef5975
+:END:
+
+Test that the binary file is saved in =./hello-world=.
+
+#+source: bin-file-1
+#+begin_src cpp :includes <iostream> :results none :compile-only t :file ./hello-world
+std::cout << "Hello World!\n";
+#+end_src
+
+Test that =yes= works, in addition to =t=.
+
+#+source: bin-file-2
+#+begin_src cpp :includes <iostream> :results none :compile-only yes :file ./hello-world
+std::cout << "Hello World!\n";
+#+end_src
+
+Error!
+
+#+source: bin-file-3
+#+begin_src cpp :includes <iostream> :results none :compile-only t
+std::cout << "Hello World!\n";
+#+end_src
diff --git a/testing/lisp/test-ob-C.el b/testing/lisp/test-ob-C.el
index c70534a51..11ec262f7 100644
--- a/testing/lisp/test-ob-C.el
+++ b/testing/lisp/test-ob-C.el
@@ -200,5 +200,37 @@ std::cout << (x == y);
                                "\"line 1\"\n\"line 2\"\n\"line 3\"\n"
                                (org-babel-execute-src-block))))))
 
+(ert-deftest ob-C/set-src+bin-file-name-1 ()
+  "Test `:compile-only' header argument."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (org-test-at-id "1a691f36-f9c1-4531-8fc0-ee7b21ef5975"
+            (org-babel-next-src-block 1)
+            (org-babel-execute-src-block)
+            (should (file-exists-p "./hello-world"))
+            (should (file-exists-p "./hello-world.cpp")))
+        (ignore-errors (delete-file "./hello-world"))
+        (ignore-errors (delete-file "./hello-world.cpp")))))
+
+(ert-deftest ob-C/set-src+bin-file-name-2 ()
+  "Test `:compile-only' header argument."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (org-test-at-id "1a691f36-f9c1-4531-8fc0-ee7b21ef5975"
+            (org-babel-next-src-block 2)
+            (org-babel-execute-src-block)
+            (should (file-exists-p "./hello-world"))
+            (should (file-exists-p "./hello-world.cpp")))
+        (ignore-errors (delete-file "./hello-world"))
+        (ignore-errors (delete-file "./hello-world.cpp")))))
+
+(ert-deftest ob-C/set-src+bin-file-name-3 ()
+  "Test `:compile-only' header argument."
+  (if (executable-find org-babel-C++-compiler)
+      (should-error
+       (org-test-at-id "1a691f36-f9c1-4531-8fc0-ee7b21ef5975"
+         (org-babel-next-src-block 3)
+         (org-babel-execute-src-block)))))
+
 (provide 'test-ob-C)
 ;;; test-ob-C.el ends here
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-13 16:09       ` Leo Butler
@ 2023-12-14 14:08         ` Ihor Radchenko
  2023-12-19 22:14           ` [PATCH] ob-C.el compile-only header argument, was " Leo Butler
  2023-12-20 18:15           ` Leo Butler
  0 siblings, 2 replies; 11+ messages in thread
From: Ihor Radchenko @ 2023-12-14 14:08 UTC (permalink / raw)
  To: Leo Butler; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

> From 7d8e406bc4a92e2e2eab772b2671dcd72ca8c202 Mon Sep 17 00:00:00 2001
> From: Leo Butler <leo.butler@umanitoba.ca>
> Date: Tue, 12 Dec 2023 12:32:41 -0600
> Subject: [PATCH] lisp/ob-C.el: add :compile-only header to compile to a named
>  target

Thanks for the patch!

> * lisp/ob-C.el (org-babel-C-execute): The new header argument,
> `:compile-only', causes source and compiled binary files to be named
> using the `:file' header argument.  When `:compile-only' is set,
> execution of source block ends at compilation.  The naming of source
> and binary filenames is factored out to `org-babel-C-src/bin-file'.

What will happen if we have something like :results value or :results
output instead of :results file link?

> * lisp/ob-C.el (org-babel-C-src/bin-file): A new function that factors
> out the setting of source and binary filenames.  It also signals an
> error if `:compile-only' is set, but `:file' is not.
> * testing/examples/ob-C-test.org: Add three example that exercise the
> `:compile-only' header argument, including one that causes an error.
> * testing/lisp/test-ob-C.el: Add three tests of the `:compile-only'
> header argument.  New tests: ob-C/set-src+bin-file-name-{1,2,3}.

You should also announce the new feature in ORG-NEWS and document it in
WORG.

> +                                    (compile-only . (nil no t yes)))

Why nil/t? No other header argument allow "nil" or "t". Just yes/no.

> +(defun org-babel-C-src/bin-file (params src? compile-only?)
> +  "Return the src or bin filename to `org-babel-C-execute'.
> +
> +If `SRC?' is T, a file extension is added to the filename.  By

Just SRC?. You should only quote Elisp symbols and upcase the function
arguments. See
https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html

Also, why upcase "T"?

> +default, the filename is created by `org-babel-temp-file'. If
> +`COMPILE-ONLY?' is T, the filename is taken from the `:file'

I think quoting :file is not necessary.

> +field in `PARAMS'; if that is NIL, an error occurs."

No need to upcase NIL.
Also, "if that is nil, throw an error" - this is more common style
(saying what function does).

> +  (let ((f (cdr (assq :file params))))

Please avoid short variable names - they are harder to understand and
search in code.

> +    (when (and compile-only? (null f))
> +      (error "Error: When COMPILE-ONLY is T or YES, output FILE needs to be set"))

t or "yes". Also, what does "output FILE" refer to? Upcasing implies
function argument, but you are referring to :file header argument in PARAMS.

> +    (let* ((file (cond (compile-only? f) (src? "C-src-") (t "C-bin-")))
> +           (ext (if src? (pcase org-babel-c-variant
> +	                   (`c ".c") (`cpp ".cpp") (`d ".d"))

We usually split `cond' and `case' into multiple lines for readability.
Otherwise, it is confusing, especially in `let' forms where one can
confuse `cond' forms with `let' bindings.

> +    (unless compile-only?
> +      (let ((results
> +	     (org-babel-eval
> ...

No return value at all? I'd expect file link to be returned, as we
discussed in another thread. Also, see the above considerations about
:results value/output. We might want return the compiler output for
:results output. Or maybe even arrange `org-babel-eval-error-notify' to
display compile-mode window when there are compilation warnings.

> --- a/testing/examples/ob-C-test.org
> +++ b/testing/examples/ob-C-test.org
> @@ -174,3 +174,29 @@ std::cout << "\"line 1\"\n";
>  std::cout << "\"line 2\"\n";
>  std::cout << "\"line 3\"\n";
>  #+end_src

If you can, please avoid adding tests as Org files where possible.
Instead, we prefer using `org-test-with-temp-text' or
`org-test-with-temp-text-in-file' when the Org fragment for the test is
not too long.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH] ob-C.el compile-only header argument, was Re: How to use mpirun with C or C++ Org-babel?
  2023-12-14 14:08         ` Ihor Radchenko
@ 2023-12-19 22:14           ` Leo Butler
  2023-12-22 12:20             ` Ihor Radchenko
  2023-12-20 18:15           ` Leo Butler
  1 sibling, 1 reply; 11+ messages in thread
From: Leo Butler @ 2023-12-19 22:14 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 4889 bytes --]

On Thu, Dec 14 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> From 7d8e406bc4a92e2e2eab772b2671dcd72ca8c202 Mon Sep 17 00:00:00 2001
>> From: Leo Butler <leo.butler@umanitoba.ca>
>> Date: Tue, 12 Dec 2023 12:32:41 -0600
>> Subject: [PATCH] lisp/ob-C.el: add :compile-only header to compile to a named
>>  target
>
> Thanks for the patch!

Thank you for the feedback.

>
>> * lisp/ob-C.el (org-babel-C-execute): The new header argument,
>> `:compile-only', causes source and compiled binary files to be named
>> using the `:file' header argument.  When `:compile-only' is set,
>> execution of source block ends at compilation.  The naming of source
>> and binary filenames is factored out to `org-babel-C-src/bin-file'.
>
> What will happen if we have something like :results value or :results
> output instead of :results file link?

Originally, I felt that only ":results file" makes sense. I have adopted
your suggestion, though, and added test cases so that the compiler
stderr output is caught.

>
>> * lisp/ob-C.el (org-babel-C-src/bin-file): A new function that factors
>> out the setting of source and binary filenames.  It also signals an
>> error if `:compile-only' is set, but `:file' is not.
>> * testing/examples/ob-C-test.org: Add three example that exercise the
>> `:compile-only' header argument, including one that causes an error.
>> * testing/lisp/test-ob-C.el: Add three tests of the `:compile-only'
>> header argument.  New tests: ob-C/set-src+bin-file-name-{1,2,3}.
>
> You should also announce the new feature in ORG-NEWS and document it in
> WORG.

I have added the announcement in this patch. I will submit a separate
patch for worg.

>
>> +                                    (compile-only . (nil no t yes)))
>
> Why nil/t? No other header argument allow "nil" or "t". Just yes/no.

Ok. I also noticed (in a separate thread) that it should be

(compile-only . ((no yes))

>
>> +(defun org-babel-C-src/bin-file (params src? compile-only?)
>> +  "Return the src or bin filename to `org-babel-C-execute'.
>> +
>> +If `SRC?' is T, a file extension is added to the filename.  By
>
> Just SRC?. You should only quote Elisp symbols and upcase the function
> arguments. See
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Documentation-Tips.html
>
> Also, why upcase "T"?

Corrected.

>
>> +default, the filename is created by `org-babel-temp-file'. If
>> +`COMPILE-ONLY?' is T, the filename is taken from the `:file'
>
> I think quoting :file is not necessary.

Yes.

>
>> +field in `PARAMS'; if that is NIL, an error occurs."
>
> No need to upcase NIL.

Yes.

> Also, "if that is nil, throw an error" - this is more common style
> (saying what function does).

Done.

>
>> +  (let ((f (cdr (assq :file params))))
>
> Please avoid short variable names - they are harder to understand and
> search in code.

Done.

>
>> +    (when (and compile-only? (null f))
>> +      (error "Error: When COMPILE-ONLY is T or YES, output FILE needs to be set"))
>
> t or "yes". Also, what does "output FILE" refer to? Upcasing implies
> function argument, but you are referring to :file header argument in PARAMS.

Ok, I think the current error message is consistent with Gnu
standards.

>
>> +    (let* ((file (cond (compile-only? f) (src? "C-src-") (t "C-bin-")))
>> +           (ext (if src? (pcase org-babel-c-variant
>> +	                   (`c ".c") (`cpp ".cpp") (`d ".d"))
>
> We usually split `cond' and `case' into multiple lines for readability.
> Otherwise, it is confusing, especially in `let' forms where one can
> confuse `cond' forms with `let' bindings.

Ok. I guess, to paraphrase, that readability is in the eye of the beholder.

>
>> +    (unless compile-only?
>> +      (let ((results
>> +	     (org-babel-eval
>> ...
>
> No return value at all? I'd expect file link to be returned, as we
> discussed in another thread. Also, see the above considerations about
> :results value/output.

See my comment above.

> We might want return the compiler output for
> :results output.

Done.

> Or maybe even arrange `org-babel-eval-error-notify' to
> display compile-mode window when there are compilation warnings.

Yes, this is already done by `org-babel-eval' in `org-babel-C-execute'.

>
>> --- a/testing/examples/ob-C-test.org
>> +++ b/testing/examples/ob-C-test.org
>> @@ -174,3 +174,29 @@ std::cout << "\"line 1\"\n";
>>  std::cout << "\"line 2\"\n";
>>  std::cout << "\"line 3\"\n";
>>  #+end_src
>
> If you can, please avoid adding tests as Org files where possible.
> Instead, we prefer using `org-test-with-temp-text' or
> `org-test-with-temp-text-in-file' when the Org fragment for the test is
> not too long.

Ok.

Patch attached.

Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-ob-C.el-add-compile-only-header-to-compile-to-a.patch --]
[-- Type: text/x-diff; name="0001-lisp-ob-C.el-add-compile-only-header-to-compile-to-a.patch", Size: 15253 bytes --]

From 37de68b264bca5f8103a1664626f1572d43f07d4 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Tue, 12 Dec 2023 12:32:41 -0600
Subject: [PATCH] lisp/ob-C.el: add :compile-only header to compile to a named
 target

* lisp/ob-C.el (org-babel-C-execute): The new header argument,
:compile-only, causes source and compiled binary files to be named
using the :file header argument.  When :compile-only is set, execution
of source block ends at compilation.  If :results is set to `output',
then any compiler errors or warnings are returned.  The naming of
source and binary filenames is factored out to
org-babel-C-src/bin-file.
* lisp/ob-C.el (org-babel-C-src/bin-file): A new function that factors
out the setting of source and binary filenames.  It also signals an
error if :compile-only is set, but :file is not.
* testing/examples/ob-C-test.org: Add six examples that exercise the
:compile-only header argument, including one that throws an error, one
that returns a compiler error message, and one that returns a compiler
warning.
* testing/lisp/test-ob-C.el: Add five tests of the :compile-only
header argument.  New tests: ob-C/set-src+bin-file-name-{1,2,3,4,5}.
* etc/ORG-NEWS: Announce the new header argument.

Refs: https://list.orgmode.org/87fs81egk5.fsf@t14.reltub.ca/
https://list.orgmode.org/87msukbadu.fsf@localhost/
---
 etc/ORG-NEWS                   |  10 +++
 lisp/ob-C.el                   | 116 ++++++++++++++++++++-------------
 testing/examples/ob-C-test.org |  57 ++++++++++++++++
 testing/lisp/test-ob-C.el      |  97 +++++++++++++++++++++++++++
 4 files changed, 236 insertions(+), 44 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 6c81221c1..09474151d 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -735,6 +735,16 @@ Completion is enabled for links to man pages added using ~org-insert-link~:
 =C-c C-l man RET emacscl TAB= to get =emacsclient=.  Of course, the ~ol-man~
 library should be loaded first.
 
+*** =ob-C.el=: add ~:compile-only~ header to compile to a named target
+
+=ob-C= has a new header argument: ~:compile-only~.
+
+The new header argument, ~:compile-only~, causes source and compiled
+binary files to be named using the ~:file~ header argument.  When
+~:compile-only~ is set, execution of source block ends at compilation.
+If ~:results~ is set to ~output~ then any compiler errors or warnings
+are returned.
+
 ** New functions and changes in function arguments
 *** ~org-fold-hide-drawer-all~ is now interactive
 
diff --git a/lisp/ob-C.el b/lisp/ob-C.el
index 0278fc02a..c07c4585c 100644
--- a/lisp/ob-C.el
+++ b/lisp/ob-C.el
@@ -53,7 +53,8 @@
 				    (main    . :any)
 				    (flags   . :any)
 				    (cmdline . :any)
-				    (libs    . :any))
+				    (libs    . :any)
+                                    (compile-only . ((no yes))))
   "C/C++-specific header arguments.")
 
 (defconst org-babel-header-args:C++
@@ -128,17 +129,35 @@ This function is called by `org-babel-execute-src-block'."
   "Expand C BODY according to its header arguments PARAMS."
   (let ((org-babel-c-variant 'c)) (org-babel-C-expand-C body params)))
 
+(defun org-babel-C-src/bin-file (params src? compile-only?)
+  "Return the src or bin filename to `org-babel-C-execute'.
+
+If SRC? is t, a file extension is added to the filename.  By
+default, the filename is created by `org-babel-temp-file'. If
+COMPILE-ONLY? is t, the filename is taken from the :file
+field in PARAMS; if that is nil, throw an error."
+  (let ((file (cdr (assq :file params))))
+    (when (and compile-only? (null file))
+      (error "Error: When compile-only header argument is \"yes\", file header argument needs to be set"))
+    (let* ((basename (cond (compile-only? file)
+                           (src? "C-src-")
+                           (t "C-bin-")))
+           (ext (if src? (pcase org-babel-c-variant
+	                   (`c ".c")
+                           (`cpp ".cpp")
+                           (`d ".d"))
+                  org-babel-exeext)))
+      (org-babel-process-file-name
+       (if compile-only? (concat basename ext)
+         (org-babel-temp-file basename ext))))))
+
 (defun org-babel-C-execute (body params)
   "Execute C/C++/D BODY according to its header arguments PARAMS.
 This function should only be called by `org-babel-execute:C' or
 `org-babel-execute:C++' or `org-babel-execute:D'."
-  (let* ((tmp-src-file (org-babel-temp-file
-			"C-src-"
-			(pcase org-babel-c-variant
-			  (`c ".c") (`cpp ".cpp") (`d ".d"))))
-	 (tmp-bin-file			;not used for D
-	  (org-babel-process-file-name
-	   (org-babel-temp-file "C-bin-" org-babel-exeext)))
+  (let* ((compile-only? (string= (cdr (assq :compile-only params)) "yes"))
+         (tmp-src-file (org-babel-C-src/bin-file params t compile-only?))
+	 (tmp-bin-file (org-babel-C-src/bin-file params nil compile-only?)) ;not used for D
 	 (cmdline (cdr (assq :cmdline params)))
 	 (cmdline (if cmdline (concat " " cmdline) ""))
 	 (flags (cdr (assq :flags params)))
@@ -155,46 +174,55 @@ This function should only be called by `org-babel-execute:C' or
 	  (pcase org-babel-c-variant
 	    (`c (org-babel-C-expand-C body params))
 	    (`cpp (org-babel-C-expand-C++ body params))
-	    (`d (org-babel-C-expand-D body params)))))
+	    (`d (org-babel-C-expand-D body params))))
+         compilation-results)
     (with-temp-file tmp-src-file (insert full-body))
     (pcase org-babel-c-variant
       ((or `c `cpp)
-       (org-babel-eval
-	(format "%s -o %s %s %s %s"
-		(pcase org-babel-c-variant
-		  (`c org-babel-C-compiler)
-		  (`cpp org-babel-C++-compiler))
-		tmp-bin-file
-		flags
-		(org-babel-process-file-name tmp-src-file)
-		libs)
-	""))
+       (let ((compile-cmd (format "%s -o %s %s %s %s"
+		                  (pcase org-babel-c-variant
+		                    (`c org-babel-C-compiler)
+		                    (`cpp org-babel-C++-compiler))
+		                  tmp-bin-file
+		                  flags
+		                  (org-babel-process-file-name tmp-src-file)
+		                  libs)))
+         (message compile-cmd)
+         (setq compilation-results
+               (org-babel-eval compile-cmd "")))
+       (if (and (string= compilation-results "") (get-buffer org-babel-error-buffer-name))
+           (setq compilation-results (with-current-buffer (get-buffer org-babel-error-buffer-name)
+                                       (buffer-substring (point-min) (point-max))))))
       (`d nil)) ;; no separate compilation for D
-    (let ((results
-	   (org-babel-eval
-	    (pcase org-babel-c-variant
-	      ((or `c `cpp)
-	       (concat tmp-bin-file cmdline))
-	      (`d
-	       (format "%s %s %s %s"
-		       org-babel-D-compiler
-		       flags
-		       (org-babel-process-file-name tmp-src-file)
-		       cmdline)))
-	    "")))
-      (when results
-	(setq results (org-remove-indentation results))
-	(org-babel-reassemble-table
-	 (org-babel-result-cond (cdr (assq :result-params params))
-	   results
-	   (let ((tmp-file (org-babel-temp-file "c-")))
-	     (with-temp-file tmp-file (insert results))
-	     (org-babel-import-elisp-from-file tmp-file)))
-	 (org-babel-pick-name
-	  (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
-	 (org-babel-pick-name
-	  (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))
-      )))
+    (cond (compile-only?
+           (org-babel-result-cond (cdr (assq :result-params params))
+             compilation-results))
+          (t
+           (let ((results
+	          (org-babel-eval
+	           (pcase org-babel-c-variant
+	             ((or `c `cpp)
+	              (concat tmp-bin-file cmdline))
+	             (`d
+	              (format "%s %s %s %s"
+		              org-babel-D-compiler
+		              flags
+		              (org-babel-process-file-name tmp-src-file)
+		              cmdline)))
+	           "")))
+             (when results
+	       (setq results (org-remove-indentation results))
+	       (org-babel-reassemble-table
+	        (org-babel-result-cond (cdr (assq :result-params params))
+	          results
+	          (let ((tmp-file (org-babel-temp-file "c-")))
+	            (with-temp-file tmp-file (insert results))
+	            (org-babel-import-elisp-from-file tmp-file)))
+	        (org-babel-pick-name
+	         (cdr (assq :colname-names params)) (cdr (assq :colnames params)))
+	        (org-babel-pick-name
+	         (cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))
+             )))))
 
 (defun org-babel-C-expand-C++ (body params)
   "Expand C/C++ BODY with according to its header arguments PARAMS."
diff --git a/testing/examples/ob-C-test.org b/testing/examples/ob-C-test.org
index c7a96f665..2212192fb 100644
--- a/testing/examples/ob-C-test.org
+++ b/testing/examples/ob-C-test.org
@@ -174,3 +174,60 @@ std::cout << "\"line 1\"\n";
 std::cout << "\"line 2\"\n";
 std::cout << "\"line 3\"\n";
 #+end_src
+
+* File naming
+:PROPERTIES:
+:ID:       1a691f36-f9c1-4531-8fc0-ee7b21ef5975
+:END:
+
+The binary file is saved in =./hello-world=.
+
+#+name: compile-only-1
+#+begin_src C++ :includes <iostream> :results none :compile-only yes :file ./hello-world
+std::cout << "Hello World!\n";
+#+end_src
+
+A link to the binary file is inserted when =:results file= is set.
+
+#+name: compile-only-2
+#+begin_src C++ :includes <iostream> :results file :compile-only yes :file ./hello-world
+std::cout << "Hello World!\n";
+#+end_src
+
+#+RESULTS: compile-only-2
+[[file:./hello-world]]
+
+Error! The =:file= header is unset.
+
+#+name: compile-only-3
+#+begin_src C++ :includes <iostream> :results none :compile-only yes
+std::cout << "Hello World!\n";
+#+end_src
+
+Syntax Error! =*Org-Babel Error Output*= buffer is popped open.  The
+contents of that buffer are also the results of this block.
+
+#+name: compile-only-4.0
+#+begin_src C++ :includes <iostream> :results output :compile-only yes :file ./hello-world
+std::cout << "Hello World!\n" <== syntax error
+#+end_src
+
+Same, except results are silenced.
+
+#+name: compile-only-4.1
+#+begin_src C++ :includes <iostream> :results none :compile-only yes :file ./hello-world
+std::cout << "Hello World!\n" <== syntax error
+#+end_src
+
+Warnings. 
+
+#+name: compile-only-5
+#+begin_src C++ :includes <iostream> :flags -Wall :results output :wrap example :compile-only yes :file ./hello-world
+int i{0};
+std::cout << "Hello World!\n";
+#+end_src
+
+
+
+
+
diff --git a/testing/lisp/test-ob-C.el b/testing/lisp/test-ob-C.el
index c70534a51..559a3aa05 100644
--- a/testing/lisp/test-ob-C.el
+++ b/testing/lisp/test-ob-C.el
@@ -200,5 +200,102 @@ std::cout << (x == y);
                                "\"line 1\"\n\"line 2\"\n\"line 3\"\n"
                                (org-babel-execute-src-block))))))
 
+(ert-deftest ob-C/compile-only-1 ()
+  "Test `:compile-only' header argument."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (let* ((file (make-temp-name "hello-world-"))
+                 (file.cpp (concat file ".cpp")))
+            (org-test-with-temp-text
+                (format "#+source: compile-only-1
+#+begin_src cpp :includes <iostream> :results none :compile-only yes :file %s
+std::cout << \"Hello World!\\n\";
+#+end_src
+" file)
+              (should (null (org-babel-execute-src-block)))
+              (should (file-exists-p file))
+              (should (file-exists-p file.cpp))))
+        (ignore-errors (delete-file file))
+        (ignore-errors (delete-file file.cpp)))))
+
+(ert-deftest ob-C/compile-only-2 ()
+  "Test `:compile-only' header argument.
+A link to the binary file should be inserted."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (let* ((file (make-temp-name "hello-world-"))
+                 (file.cpp (concat file ".cpp")))
+            (org-test-with-temp-text
+                (format "#+source: compile-only-2
+#+begin_src cpp :includes <iostream> :results file :compile-only yes :file %s
+std::cout << \"Hello World!\\n\";
+#+end_src
+" file)
+              (should (string= file (org-babel-execute-src-block)))
+              (should (file-exists-p file))
+              (should (file-exists-p file.cpp))))
+        (ignore-errors (delete-file file))
+        (ignore-errors (delete-file file.cpp)))))
+
+(ert-deftest ob-C/compile-only-3 ()
+  "Test `:compile-only' header argument.
+The :file header is unset, which throws an error."
+  (if (executable-find org-babel-C++-compiler)
+      (org-test-with-temp-text
+          (format "#+source: compile-only-3
+#+begin_src cpp :includes <iostream> :results file :compile-only yes
+std::cout << \"Hello World!\\n\";
+#+end_src
+")
+        (should-error (org-babel-execute-src-block)))))
+
+(ert-deftest ob-C/compile-only-4 ()
+  "Test `:compile-only' header argument.
+
+A C++ syntax error throws a compiler error.  The compiler's error
+output is caught in `org-babel-error-buffer-name'; that buffer's
+contents are the result of the source block."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (let* ((file (make-temp-name "hello-world-"))
+                 (file.cpp (concat file ".cpp")))
+            (org-test-with-temp-text
+                (format "#+source: compile-only-4.0
+#+begin_src cpp :includes <iostream> :results output :compile-only yes :file %s
+std::cout << \"Hello World!\\n\" <== syntax error
+#+end_src
+" file)
+              (should (string-match "error:" (org-babel-execute-src-block)))
+              (should (get-buffer org-babel-error-buffer-name))
+              (should (file-exists-p file.cpp))))
+        (ignore-errors (kill-buffer org-babel-error-buffer-name))
+        (ignore-errors (delete-file file))
+        (ignore-errors (delete-file file.cpp)))))
+
+(ert-deftest ob-C/compile-only-5 ()
+  "Test `:compile-only' header argument.
+
+A C++ warning is emitted on stderr.  The compiler's warning is
+caught in `org-babel-error-buffer-name'; that buffer's contents
+are the result of the source block."
+  (if (executable-find org-babel-C++-compiler)
+      (unwind-protect
+          (let* ((file (make-temp-name "hello-world-"))
+                 (file.cpp (concat file ".cpp")))
+            (org-test-with-temp-text
+                (format "#+source: compile-only-4.0
+#+begin_src cpp :includes <iostream> :flags -Wall :results output :compile-only yes :file %s
+int i;
+std::cout << \"Hello World!\\n\";
+#+end_src
+" file)
+              (should (string-match "warning:" (org-babel-execute-src-block)))
+              (should (get-buffer org-babel-error-buffer-name))
+              (should (file-exists-p file.cpp))))
+        (ignore-errors (kill-buffer org-babel-error-buffer-name))
+        (ignore-errors (delete-file file))
+        (ignore-errors (delete-file file.cpp)))))
+
+
 (provide 'test-ob-C)
 ;;; test-ob-C.el ends here
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: How to use mpirun with C or C++ Org-babel?
  2023-12-14 14:08         ` Ihor Radchenko
  2023-12-19 22:14           ` [PATCH] ob-C.el compile-only header argument, was " Leo Butler
@ 2023-12-20 18:15           ` Leo Butler
  1 sibling, 0 replies; 11+ messages in thread
From: Leo Butler @ 2023-12-20 18:15 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

[-- Attachment #1: Type: text/plain, Size: 564 bytes --]

On Thu, Dec 14 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>> From 7d8e406bc4a92e2e2eab772b2671dcd72ca8c202 Mon Sep 17 00:00:00 2001
>> From: Leo Butler <leo.butler@umanitoba.ca>
>> Date: Tue, 12 Dec 2023 12:32:41 -0600
>> Subject: [PATCH] lisp/ob-C.el: add :compile-only header to compile to a named
>>  target
>
> Thanks for the patch!
>
> You should also announce the new feature in ORG-NEWS and document it in
> WORG.
>

Attached is the patch to WORG that documents the change.

Leo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ob-doc-C.org-document-compile-only-header.patch --]
[-- Type: text/x-diff; name="0001-ob-doc-C.org-document-compile-only-header.patch", Size: 4902 bytes --]

From 927a255e6c4abb34bf797f120c7a5186b7f113b7 Mon Sep 17 00:00:00 2001
From: Leo Butler <leo.butler@umanitoba.ca>
Date: Wed, 20 Dec 2023 12:06:13 -0600
Subject: [PATCH] ob-doc-C.org: document compile-only header

* org-contrib/babel/languages/ob-doc-C.org: Add :compile-only to the
list of header arguments.  Add a subsection, Compiling to a named
binary, that describes its use.

Ref:
https://list.orgmode.org/orgmode/87h6kdyh52.fsf_-_@t14.reltub.ca/T/#u
---
 org-contrib/babel/languages/ob-doc-C.org | 114 +++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/org-contrib/babel/languages/ob-doc-C.org b/org-contrib/babel/languages/ob-doc-C.org
index 14d83135..89f6e91f 100644
--- a/org-contrib/babel/languages/ob-doc-C.org
+++ b/org-contrib/babel/languages/ob-doc-C.org
@@ -69,6 +69,31 @@ the results of evaluation inserted into the buffer.
 : #+results:
 : : 2
 
+With C and C++, =ob-C.el= can also compile code to a named binary.
+
+#+name: c++-compile-only.org
+#+begin_src org :exports code :results replace
+,#+name: c++-compile-only
+,#+header: :file ./hello-world
+,#+header: :results file
+,#+header:  :includes <iostream>
+,#+begin_src C++
+std::cout << "Hello World++\n";
+,#+end_src
+#+end_src
+
+#+RESULTS: c++-compile-only.org
+#+name: c++-compile-only
+#+header: :file ./hello-world
+#+header: :results file
+#+header:  :includes <iostream>
+#+begin_src C++
+std::cout << "Hello World++\n";
+#+end_src
+
+: #+RESULTS: c++-compile-only
+: [[file:./hello-world]]
+
 ** About C
 C dates back to the 1970's.
 It was devised by Kernighan and Ritchie.
@@ -167,6 +192,10 @@ It features:
      (C & C++ only) useful for linking with a library, may be given
      =-L/path/to/lib= and =-llibrary= instructions.
 
+- =:compile-only= ::
+     (C & C++ only) compile the code block. The compiled binary is
+     /not/ executed; this file is named by the =:file= header argument.
+
 ** Sessions
    There is no support for sessions
 
@@ -256,6 +285,91 @@ When several libraries need to be included, =:includes= value should be set to a
 : Hello World!
 : 4
 
+** Compiling to a named binary
+:PROPERTIES:
+:ID:       0bf900ad-b1f3-4484-824b-cff84873e3d6
+:END:
+
+To compile source code to a dedicated binary, set the header argument
+~:compile-only~ to ~yes~. In this case, the binary file is /not/
+executed when the code block is evaluated. The results of the code
+block can also be inserted into the Org file.
+
+*** Compiling =hello-world=
+
+Set the ~:compile-only~ header argument to ~yes~ to produce the binary
+file =hello-world=. Note that an unset ~:file~ header argument throws
+an error.
+
+#+name: compile-only-insert-link.org
+#+begin_src org :exports code :results replace
+,#+name: compile-only-insert-link
+,#+header: :compile-only yes
+,#+header: :results file
+,#+header: :file ./hello-world
+,#+header: :includes <iostream>
+,#+begin_src C++
+std::cout << "Hello World!\n";
+,#+end_src
+#+end_src
+
+#+RESULTS: compile-only-insert-link.org
+#+name: compile-only-insert-link
+#+header: :compile-only yes
+#+header: :results file
+#+header: :file ./hello-world
+#+header: :includes <iostream>
+#+begin_src C++
+std::cout << "Hello World!\n";
+#+end_src
+
+With ~:results file~, evaluation of the code block inserts a link to
+the binary:
+
+: #+RESULTS: compile-only-insert-link
+: [[file:./hello-world]]
+
+*** Outputting compilation errors
+
+When ~:results output~ is set on the code block, compiler errors and
+warnings are inserted as results of the code block. In this example, a
+semi-colon is omitted, which throws a syntax error.
+
+#+name: compile-only-errors.org
+#+begin_src org :exports code :results replace
+,#+name: compile-only-errors
+,#+header: :compile-only yes
+,#+header: :results output
+,#+header: :file ./hello-world
+,#+header: :includes <iostream>
+,#+begin_src C++
+std::cout << "Hello World!\n"
+,#+end_src
+#+end_src
+
+#+RESULTS: compile-only-errors.org
+#+name: compile-only-errors
+#+header: :compile-only yes
+#+header: :results output
+#+header: :file ./hello-world
+#+header: :includes <iostream>
+#+begin_src C++
+std::cout << "Hello World!\n"
+#+end_src
+
+The result of evaluation of the code block is the compiler message
+(pathnames elided):
+
+#+RESULTS: compile-only-errors
+: ./hello-world.cpp: In function ‘int main()’:
+: ./hello-world.cpp:9:30: error: expected ‘;’ before ‘return’
+:     9 | std::cout << "Hello World!\n"
+:       |                              ^
+:       |                              ;
+:    10 | return 0;
+:       | ~~~~~~                        
+: [ Babel evaluation exited with code 1 ]
+
 ** Note that:
 - if no =main()= is declared, a trivial one is automatically provided,
 - there is no directive like:
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] ob-C.el compile-only header argument, was Re: How to use mpirun with C or C++ Org-babel?
  2023-12-19 22:14           ` [PATCH] ob-C.el compile-only header argument, was " Leo Butler
@ 2023-12-22 12:20             ` Ihor Radchenko
  2024-01-04 17:53               ` Leo Butler
  0 siblings, 1 reply; 11+ messages in thread
From: Ihor Radchenko @ 2023-12-22 12:20 UTC (permalink / raw)
  To: Leo Butler; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>> What will happen if we have something like :results value or :results
>> output instead of :results file link?
>
> Originally, I felt that only ":results file" makes sense. I have adopted
> your suggestion, though, and added test cases so that the compiler
> stderr output is caught.

Thanks! This makes sense, but now the default behaviour (when no :results
type is specified) is unexpected.

When you have something like

#+begin_src C :compile-only t :file foo :includes "stdio.h"
printf("This is test");
#+end_src

, executing should yield file link, even though it is not explicitly
specified.

And when you have compilation error,

#+begin_src C :compile-only t :file foo :includes "stdio.h"
printf("This is test")
#+end_src

the result may be empty - buffer displayed by `org-babel-eval' is
probably enough.

Basically, Org babel promises DWIM behavior when :results type is not
explicitly stated.

P.S. In my testing, I wrote

#+begin_src C :compile-only t :file foo :includes "stdio.h"
(printf "This is test")
#+end_src

and was staring at the compilation error for a good minute, trying to
understand what the hell did I do wrongly 🤦.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] ob-C.el compile-only header argument, was Re: How to use mpirun with C or C++ Org-babel?
  2023-12-22 12:20             ` Ihor Radchenko
@ 2024-01-04 17:53               ` Leo Butler
  2024-01-05 12:47                 ` Ihor Radchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Leo Butler @ 2024-01-04 17:53 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

On Fri, Dec 22 2023, Ihor Radchenko <yantar92@posteo.net> wrote:

> Leo Butler <Leo.Butler@umanitoba.ca> writes:
>
>>> What will happen if we have something like :results value or :results
>>> output instead of :results file link?
>>
>> Originally, I felt that only ":results file" makes sense. I have adopted
>> your suggestion, though, and added test cases so that the compiler
>> stderr output is caught.
>
> Thanks! This makes sense, but now the default behaviour (when no :results
> type is specified) is unexpected.
>
> When you have something like
>
> #+begin_src C :compile-only t :file foo :includes "stdio.h"
> printf("This is test");
> #+end_src

It should be "yes" not "t".

>
>
> , executing should yield file link, even though it is not explicitly
> specified.

Ok. But, isn't it a responsibility of org-babel to ensure that if :file
is set and :results is not, then the parameter list that is passed to
org-babel-*-execute includes a correctly set :result-params field
(i.e. it includes "file")? I mean, the docs say [1]:

‘file’                                                                  
     Interpret as a filename.  Save the results of execution of the code
     block to that file, then insert a link to it.  

I would prefer not to fiddle in ob-*.el to implement a policy that
should be implemented at a higher level.

[1] (info "(org) Results of Evaluation"):

>
> And when you have compilation error,
>
> #+begin_src C :compile-only t :file foo :includes "stdio.h"
> printf("This is test")
> #+end_src
>
>
> the result may be empty - buffer displayed by `org-babel-eval' is
> probably enough.

Can you tell me what behaviour you expect? No #+RESULTS: ?

>
> Basically, Org babel promises DWIM behavior when :results type is not
> explicitly stated.

I am happy to modify the patch to make ob-C.el conform to the stated (or
implied) Org policies. But, "dwim" hurts my head.

>
> P.S. In my testing, I wrote
>
> #+begin_src C :compile-only t :file foo :includes "stdio.h"
> (printf "This is test")
> #+end_src
>
> and was staring at the compilation error for a good minute, trying to
> understand what the hell did I do wrongly 🤦.

Ahhh! Lisp syntax is so much nicer to read.

Happy New Year,
Leo

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] ob-C.el compile-only header argument, was Re: How to use mpirun with C or C++ Org-babel?
  2024-01-04 17:53               ` Leo Butler
@ 2024-01-05 12:47                 ` Ihor Radchenko
  0 siblings, 0 replies; 11+ messages in thread
From: Ihor Radchenko @ 2024-01-05 12:47 UTC (permalink / raw)
  To: Leo Butler; +Cc: tbanelwebmin, emacs-orgmode@gnu.org

Leo Butler <Leo.Butler@umanitoba.ca> writes:

>> #+begin_src C :compile-only t :file foo :includes "stdio.h"
>> printf("This is test");
>> #+end_src
>
> It should be "yes" not "t".

I tested with :compile-only yes, but it did not change the observed
issue.

>> , executing should yield file link, even though it is not explicitly
>> specified.
>
> Ok. But, isn't it a responsibility of org-babel to ensure that if :file
> is set and :results is not, then the parameter list that is passed to
> org-babel-*-execute includes a correctly set :result-params field
> (i.e. it includes "file")? I mean, the docs say [1]:
>
> ‘file’                                                                  
>      Interpret as a filename.  Save the results of execution of the code
>      block to that file, then insert a link to it.  
>
> I would prefer not to fiddle in ob-*.el to implement a policy that
> should be implemented at a higher level.
>
> [1] (info "(org) Results of Evaluation"):

No, it is not the responsibility of ob-core. Simply because :file "name"
may imply multiple things that only the backend can determine.

:results value :file foo.txt means "execute src block, take its return
value, and save it to file foo.txt"

:results file link :file foo.txt means a completely different thing -
"execute src block for side effect, and insert link to file specified in
:file argument; assume that the file is created by the side effect"

So, when :results is not specified, ob-core leaves it up to the backend
to decide what kind of output to produce.

>> Basically, Org babel promises DWIM behavior when :results type is not
>> explicitly stated.
>
> I am happy to modify the patch to make ob-C.el conform to the stated (or
> implied) Org policies. But, "dwim" hurts my head.

May you please elaborate why "dwim" is a problem?

>> And when you have compilation error,
>>
>> #+begin_src C :compile-only t :file foo :includes "stdio.h"
>> printf("This is test")
>> #+end_src
>>
>> the result may be empty - buffer displayed by `org-babel-eval' is
>> probably enough.
>
> Can you tell me what behaviour you expect? No #+RESULTS: ?

No. The purpose of this example was to illustrate that the same set of
header arguments should _not_ yield [[file:foo]] link in the results, in
contrast to when no compilation error is produced.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2024-01-05 12:44 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-07 23:10 How to use mpirun with C or C++ Org-babel? Edgar Lux
2023-12-08 10:36 ` tbanelwebmin
2023-12-08 15:47   ` Leo Butler
2023-12-08 22:24     ` Ihor Radchenko
2023-12-13 16:09       ` Leo Butler
2023-12-14 14:08         ` Ihor Radchenko
2023-12-19 22:14           ` [PATCH] ob-C.el compile-only header argument, was " Leo Butler
2023-12-22 12:20             ` Ihor Radchenko
2024-01-04 17:53               ` Leo Butler
2024-01-05 12:47                 ` Ihor Radchenko
2023-12-20 18:15           ` Leo Butler

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).