I have been trying to figure out a way to efficiently save a program, compile it and then run it in emacs. I have succeeded only partially in it.
I use smart-compile.el to make the job easier ( http://emacswiki.org/emacs/smart-compile.el ).
In that I have edited the C++ relevant portion to the below so that a program compiles and runs when I type M-x smart-compile RET followed by a RET.
(defcustom smart-compile-alist '(
;; g++-3 is used instead of g++ as the latter does not
;; work in Windows. Also '&& %n' is added to run the
;; compiled object if the compilation is successful
("\\.[Cc]+[Pp]*\\'" . "g++-3 -O2 -Wall -pedantic -Werror
-Wreturn-type %f -lm -o %n && %n")
..
To give an example, for a program sqrt.cpp, smart-compile auto generates following compile command:
g++-3 -O2 -Wall -pedantic -Werror -Wreturn-type sqrt.cpp -lm -o sqrt && sqrt
This works as long as my .cpp does not have any cin statement. For codes with cin statements, the console window shows the point where the user is supposed to input data. But I am unable to input anything and the Compilations status stays stuck at running.
In order to make the codes with user input work, I have to remove the && FILENAME part and then manually run ./FILENAME in emacs' eshell.
I am running emacs 24.3 in Windows. I have Cygwin installed and its bin added to the Windows environment variable Path (that's why g++-3 compilation works).
I would appreciate if someone could guide me how to save-compile-run user input required .cpp programs in emacs using a single command. Or at least how do I need to modify the above g++-3 command to make compile+run work for user input programs.
Thanks!
Emacs is programmable, so if something requires two steps, you can write a command that combines them. The simples code would look like this:
(defun save-compile-execute ()
(interactive)
(smart-compile 1) ; step 1: compile
(let ((exe (smart-compile-string "%n"))) ; step 2: run in *eshell*
(with-current-buffer "*eshell*"
(goto-char (point-max))
(insert exe)
(eshell-send-input))
(switch-to-buffer-other-window "*eshell*")))
The above code is simple, but it has one flaw: it doesn't wait for the compilation to finish. Since smart-compile doesn't support a flag for synchronous compilation, this must be achieved by temporarily hooking into the compilation-finish-functions, which makes the code more complex:
(require 'cl) ; for lexical-let
(defun do-execute (exe)
(with-current-buffer "*eshell*"
(goto-char (point-max))
(insert exe)
(eshell-send-input))
(switch-to-buffer-other-window "*eshell*"))
(defun save-compile-execute ()
(interactive)
(lexical-let ((exe (smart-compile-string "./%n"))
finish-callback)
;; when compilation is done, execute the program
;; and remove the callback from
;; compilation-finish-functions
(setq finish-callback
(lambda (buf msg)
(do-execute exe)
(setq compilation-finish-functions
(delq finish-callback compilation-finish-functions))))
(push finish-callback compilation-finish-functions))
(smart-compile 1))
The command can be run with M-x save-compile-execute RET or by binding it to a key.
Related
I'm trying to learn how to compile CPP into WASM and I can't seem get it to work properly.
I have a simple CPP code that implements a squarer function which squares a given integer:
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
int EMSCRIPTEN_KEEPALIVE squarer(int num) {return num * num;}
I can compile this into WASM but when I try to load it in JS it says there are no exported functions.
Looking at the WAT version (by running wasm2wat from wabt) it is clear that the problem is that the squarer function is not being exported.
(module
(type $t0 (func (param i32) (result i32)))
(import "env" "__linear_memory" (memory $env.__linear_memory 0))
(import "env" "__indirect_function_table" (table $env.__indirect_function_table 0 funcref))
(func $_Z7squareri (type $t0) (param $p0 i32) (result i32)
(i32.mul
(local.get $p0)
(local.get $p0))))
So I tried to compile again with the EXPORTED_FUNCTIONS flag (see the following line), but I get the following warning and the squarer function is still not being exported.
$ emcc squarer.cc -o squarer.wasm -c -O1 -s EXPORTED_FUNCTIONS="_Z7squareri","squarer"
emcc: warning: linker setting ignored during compilation: 'EXPORTED_FUNCTIONS' [-Wunused-command-line-argument]
When I edited the WAT to include an export (by changing func $_Z7squareri to func (export "squarer")) and compiled it back to WASM the JS successfully loaded the function, so it seems that the missing export really is the problem.
I tested it on two linux machines (one running ubuntu 20.04 and the other 18.04, both with the latest version of emsdk downloaded from their github as per the instructions in the MDN website).
I also tried using all of the other emcc flags with "EXPORT" in them but they all got the same warning.
This is my first time building a WASM module, and I learned everything from the internet so I might have missed some crucial step. Am I doing it wrong?
Am I using outdated tools?
Is there a better / newer CPP to WASM compiler I should be using?
Thanks!
Ittai
The -c command line option produces a wasm object file which is not designed to be executed directly. You need to then link that object file using emcc (without -c) to get the final binary.
You can do both compiling and linking in single command by simply removing the -c from the example command line you give above.
If you use EMSCRIPTEN_KEEPALIVE you don't need EXPORTED_FUNCTIONS on the command line as they serve the same purpose.
Is there a way I can make emacs compile and run my code in an external console window with the command M-x compile (what I mean by external console window is that I want it to run my code in a new console window like it does when I run my C++ code in visual studio).
I want emacs to automatically open up a new console window and run the executable after M-x compile like this:
Normally with Emacs, when you want some obscure (i.e. some simple, or special to your use case) automation, you just write a command, which does what you want.
Here is such an example. Following Elisp code calls a function and-run, when compilation is finished (through using hook compilation-finish-functions).
(defun and-run (&rest _)
"run after comilation, an not elaborated example function"
(interactive)
(let ((exe "./test.out")
(prevent-closing (concat "echo \"Press Enter to continue\"" ";"
"read"))
(terminal "xterm -e"))
(when (file-exists-p exe)
(let ((my-command (concat exe ";" prevent-closing)))
(shell-command (format "%s %s" terminal (shell-quote-argument my-command)))))))
(add-hook 'compilation-finish-functions #'and-run)
Since I'm no Windows user you have to make some small adaptions to this function, in order to be able to run it on Windows.
Note: there is also a compilation-start-hook, if you e.g. want to compare file-modification times of your exe.
Since everything is 32-bit, I used :set makeprg=mingw32-make, and then tried compiling via :!make, which gave the following error message:
'make' is not recognized as an internal or external command, operable program or batch file.
shell returned 1
I tried the basic "Goodbye World" stuff:
#include <iostream>
int main() {
std::cout << "Goodbye World";
return 0;
}
What am I doing wrong? Other than being a noob.
:!make doesn't run 'makeprg'. It runs make. Since you are specifically trying to run mingw32-make.exe, presumably you don't have an executable named make.exe. (See :help :!)
:make runs 'makeprg'. (See :help :make, :help 'makeprg')
my goal is to see the "Goodbye World" either in console or terminal or any observable way. Would this require additional tinkering to the _vimrc file?
You would rather want to do it by tinkering with your makefile. Any arguments to :make will be passed to 'makeprg'. If you defined targets clean (to remove the Make artefacts) or run (to execute the product of your Make), you will be able to write :mak clean or :mak run in Vim to run those targets. Obviously, you can create your own commands and/or mappings to make those :make commands faster.
Note (and I completely overlooked this myself, silly me) that when you run a simple code, such as the one above, that does not need extensive file managements and Makefiles, all you need to go is :!gcc % for C and :!g++ % for C++. I believe (and I may be wrong, but this is a simple observation) that in Vim, :! indicates the following commands are to be executed in the system Command Prompt, and gcc/g++ is the command to invoke the GNU Compiler for C and C++ respectively. Finally, % is used to indicate the current filename, with all extensions intact. This is extremely useful in cases of keymapping, as I have done via the following:
nnoremap <F5> :!g++ %<CR>|"Press Func.5 to Compile via GNU Comp.
We are trying to test for -pthread availability and set the flag in both CXXFLAGS and LDFLAGS. We don't want to use ax_pthread because it uses the wrong compiler and sets the wrong flags for a C++ project. And according to Significance of -pthread flag when compiling, -pthread is most portable, so we want to use it for both CXXFLAGS and LDFLAGS.
The scripting we added to configure.ac is:
AC_ARG_ENABLE(tls,
AS_HELP_STRING([--enable-tls], [enable thread storage (default is yes)]),
ac_enable_tls=$enableval,
ac_enable_tls=yes)
AM_CONDITIONAL(HAS_PTHREADS, test $ac_enable_tls = yes)
if test "$ac_enable_tls" = "yes"; then
SAVED_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="-pthread"
AC_MSG_CHECKING([for pthread support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([-pthread]) && AC_SUBST([AM_CXXFLAGS], ["-pthread"]) && AC_SUBST([AM_LDFLAGS], ["-pthread"])],
[AC_MSG_FAILURE(["--enable-tls=yes but pthreads are not available"])]
)
CXXFLAGS="$SAVED_CXXFLAGS"
fi
It results in:
./configure: line 16173: syntax error near unexpected token `&&'
./configure: line 16173: ` && AM_LDFLAGS="-pthread"'
autoreconf --warnings=all produces no warnings related to the test.
I'm guessing the trouble is trying to do three things in AC_COMPILE_IFELSE and [action-if-true]. The Autoconf AC_COMPILE_IFELSE docs don't tell us how to handle the situation and does not provide examples.
We want to perform three actions in [action-if-true]:
Print the message pthread
AM_CXXFLAGS += -pthread
AM_LDFLAGS += -pthread
How do I perform multiple actions in [action-if-true]?
It is not clear to me why you use the && shell operator; it will not work if the preceding m4 macro emits a newline. You should consider using ; or simply multiple lines.
It's also quite common in configure scripts just to set a shell variable in the AC_COMPILE_IFELSE actions, and check that afterwards. This avoids deeply nested shell code, and issues related to m4 quoting/macro expansion. Here is an example from glibc:
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <sys/sdt.h>
void foo (int i, void *p)
{
asm ("" STAP_PROBE_ASM (foo, bar, STAP_PROBE_ASM_TEMPLATE (2)) ""
:: STAP_PROBE_ASM_OPERANDS (2, i, p));
}]])], [libc_cv_sdt=yes], [libc_cv_sdt=no])
I am basically executing:
ocamlmktop -o mytoplevel 1.cmo 2.cmo
and I get by an executable toplevel. The question is how do I make aquamacs run that toplevel?
It depends of the Emacs mode that you use to develop in OCaml under Aquamacs. As tuareg-mode is by far the most popular choice, I consider this case.
You usually start an OCaml toplevel with the command M-x tuareg-run-ocaml which prompts for a toplevel to start. You can here enter the path to your custom toplevel.
The toplevel proposed by tuareg-run-ocaml is actually the value of the variable tuareg-interactive-program, you can take advantage of this to define a custom tuareg-run-mytoplevel function with:
(defun tuareg-run-mytoplevel ()
(interactive)
(let ((tuareg-interactive-program "/path/to/mytoplevel"))
(tuareg-run-ocaml)))
If you put this definition in your ~/.emacs, you can then use the command M-x tuareg-run-mytoplevel to start your own toplevel.