* 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: [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
* 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
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).