compile large project within emacs - emacs

A large project may have directory with several level depth. Emacs's default compile command is "make -k", if I modified a certain source code, then typed "M-x compile RET RET", it will execute "make -k" under the directory which the source code lies.
I think I can write a function to determine if the Makefile exist under current directory, if yes, keep searching under the parent directory until find the top level directory, then execute the building command, it would be right like my expectation.
However, I'm not very clearly how to start, could anyone give me some hints to start? Like the function or variable I may encounter. Thanks.

You can try to use something like:
(setq compile-command
'(let ((mf (locate-dominating-file default-directory "Makefile")))
(if mf (setq mf (file-name-directory mf)))
(concat (if (and mf (not (equal mf default-directory)))
(format "cd %s; "
(shell-quote-argument
(file-relative-name
(directory-file-name mf)))))
"make -k ")))

There is a smarter-compile in marmalade.
From the documentation....When you require it, you can specify a list of cons cells, each one like (TEST . COMMAND).
COMMAND is used for the compile-command when
the TEST succeeds.
TEST can be:
a string. In this case it is used as a regex,
and matched against the filename associated to the
buffer. The TEST succeeds when the regex matches.
a symbol, representing the major-mode. In this case
if the buffer uses that major mode, the TEST
succeeds.
a symbol, representing any function with a name not
ending in \"-mode\". In this case, the function is
called and if it returns non-nil, the TEST
succeeds.
a list of forms. In this case the forms are eval'd,
and if the return value is non-nil, the TEST
succeeds.
So you could produce a function that does the scan for makefile in parent directories,
and use that as your TEST.
According to the documentation, if the COMMAND is nil, then the package uses the result of the TEST as the compile command. Which means you would need only one function, returning a make command referencing the makefile in the appropriate directory.

Take a look at: http://emacswiki.org/emacs/CompileCommand
"C-h v compile-command" directly from emacs.

Here's a solution for people who prefer bash scripting over Emacs Lisp. In my .emacs I define a command which saves all buffers and runs a bash script which compiles the project.
(defun save-all-and-compile () (interactive)
(save-some-buffers 1)
(shell-command "make-and-run.sh &"))
(add-hook 'c-mode-common-hook (lambda ()
(local-set-key (kbd "<f5>") 'save-all-and-compile)))
For small projects the script could be as simple as
#!/bin/bash
make -j && ./<main>
where 'main' is the name of your executable. For larger projects one would first need to locate the root directory. Similarly, you could have different scripts (bound for different keys) for building and running the program. And then some more scripts for testing different parts of the project. But these are just details one can figure out for themselves.
Make sure the script is run asynchronously using '&'. This way the Async Shell Command buffer will open with the output from make and your project and will stay open.
EDIT
Based on the discussion below it appears I have initially overthought it and the solution is quite simple. Instead of passing the usual 'make' or 'make -k' to compile-command one could use a shell script which first navigates to the project's root directory and the builds.
(setq compile-command "script.sh")

Related

irony-mode does not pick up include paths

I've recently started using irony-mode for completion in emacs (24.3.1). However, I seem unable to add additional system include paths to package.
I have this code in my config:
(defun ac-cc-mode-clang-hooks ()
(yas/minor-mode-on)
(auto-complete-mode 1)
;; avoid enabling irony-mode in modes that inherits c-mode, e.g: php-mode
(when (member major-mode irony-known-modes)
(irony-mode 1))
;; set compiler flags to include header files
(setq irony-compile-flags '("-Iinc"))
(irony-reload-flags))
(add-hook 'c++-mode-hook 'ac-cc-mode-clang-hooks)
(add-hook 'c-mode-hook 'ac-cc-mode-clang-hooks)
irony-mode is loaded correctly and completion works perfectly for include paths which the compiler knows explicitly (i.e. everything printed by echo "" | g++ -v -x c++ -E -) but the additional include path inc is not picked up (does not matter whether its a relative or absolute path).
However, if I add the information to the .clang_complete file and load it using C-c C-b the include path is recognised and used. Obviously this is a less than ideal setup because
I don't want to create a .clang_complete file for each single piece of code I'm working on
The .clang_complete file is not loaded automatically.
Is there some working method (which does not involve a per-project setup, I don't want to create project management files for each piece of code) for telling irony-mode where to look for header files?
You can take a look here: https://github.com/Sarcasm/irony-mode#i-got-an-error-due-to-stdargh-how-to-solve-this
The variable irony-libclang-additional-flags should meet your needs.
It should work without calling irony-reload-flags.
It's not a buffer-local variable though, so you don't need to put it in the hook.
I would recommend the following:
(setq irony-libclang-additional-flags
(append '("-I" "inc") irony-libclang-additional-flags))

In emacs, running a command before each p4 command

So at work, I've got to work from two different repositories. The files map to essentially the same place, but one path has 'data' in it.
It's relatively trivial to write a defun that determines if the file is in the data directory or not, and so which repository I actually want to check out from. But I can't figure out a way to call my function before any p4 commands without explicitly rebinding the keys to do it, and even that is sort of a big hack. I'd really just like it to run every time I try to check out or revert a file and set the p4port as I want it to.
All the hooks in the p4 system seem to be called when I don't want them to be. I tried calling my defun on the p4-mode-hook, but that hook only runs when the mode is set, and files that aren't in the repository are rejected before I ever get my defun to do anything. :/
There are a couple of approaches that you could use. First, you could consider adding the desired functions to pre-command-hook, with a predicate to check whether the current buffer is operating in p4-mode, i.e.:
(add-hook
'pre-command-hook
(lambda ()
(when (eq major-mode 'p4-mode)
;;; specify whatever functions you desire
)))
This will indiscriminately execute the functions that you include in the body of the above lambda before any command in a p4-mode buffer. If that's overkill and you need to be more selective about when to execute said functions, you should probably individually advise each of the p4 commands that should first execute your functions before running, e.g.:
(defadvice
name-of-p4-function
(before name-of-p4-function-advice activate)
;;; functions to be executed
)
(ad-activate 'name-of-p4-function)
See the Advising functions section of the Emacs manual for additional details.

Emacs: Set tab indent for just one file on the fly

I work on an open source project where the creator sets his tab-indents to 2 spaces.
I'd like to just enable it on the fly for the one file I work on and not other files of the same type. There must be something like M-x set-tab-indent. It is a JavaScript file ending in .js.
I know I can use:
(setq-default tab-width int)
inside my .emacs file, but I rather just call an M-x command to set it and forget it during my duration of working on this file. I tried M-x apropos and Google but couldn't find the specific command.
Thanks.
You can make the variable js-indent-level local to the buffer using:
M-x make-variable-buffer-local <RET> js-indent-level <RET>
Then you can set that variable in the buffer using:
M-x set-variable <RET> js-indent-level <RET> 2
The easiest way to do this for a single buffer is to use M-x set-variable.
Type M-x set-variable and press enter
When prompted for the variable to set, set tab-width then press enter
You'll be prompted with the line Set tab-width (buffer-local) to value:.
Put the value you want, then hit enter
The buffer should instantly be updated with the new value.
You could also use file local variables to automate omrib's solution for that one file, by adding this to it:
// Local Variables:
// js-indent-level: 2
// indent-tabs-mode: nil
// End:
Create a file ".dir-locals.el" in the project's directory and fill it like this:
((nil . ((tab-width . 2))))
This will take care of setting tab-width automatically and you don't have to modify the actual file (which is likely version-controlled.)
See the manual for more information about the format. I believe this requires Emacs 23.
As indicated by others, one issue with the File Local Variables approach is that you need to modify the file, and that's not ideal if you need to keep those declarations out of version control.
If you want the variables to apply to all files under a given directory, then Directory Local Variables is obviously the way to go, and you can implement that with either a .dir-locals.el file, or by calling (dir-locals-set-directory-class):
http://www.emacswiki.org/emacs/DirectoryVariables
http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html
I prefer the directory class approach myself, and I was thinking that it's a shame that there isn't an analogous approach for file local variables, but I found that the directory class code actually works perfectly with files, and the only issue is that dir-locals-set-directory-class calls file-name-as-directory on its argument, which prevents it from being matched, due to the trailing slash.
The following therefore is a way to configure directory local variables for a single file, without modifying the file itself, or affecting other files under the same parent directory.
(defun my-file-locals-set-directory-class (file class &optional mtime)
"Enable 'directory local' classes for individual files,
by allowing non-directories in `dir-locals-directory-cache'.
Adapted from `dir-locals-set-directory-class'."
(setq file (expand-file-name file))
(unless (assq class dir-locals-class-alist)
(error "No such class `%s'" (symbol-name class)))
(push (list file class mtime) dir-locals-directory-cache))
(dir-locals-set-class-variables
'my-javascript-class
'((nil . ((js-indent-level . 2)
(indent-tabs-mode . nil)))))
(my-file-locals-set-directory-class
"path/to/the/file.js" 'my-javascript-class)
I use a snippet of code in my init.el that tries to auto-detect files that use 2-space indents, and switch Emacs's indentation for that file to 2 spaces when it sees such files:
(add-hook 'js-mode-hook
(lambda ()
(when (string-match-p "^ [A-Za-z]" (buffer-string))
(make-variable-buffer-local 'js-indent-level)
(set-variable 'js-indent-level 2))))

emacs23 / elisp: how to properly autoload this library?

I am upgrading to emacs23. I find that my emacs.el loads much more slowly.
It's my own fault really... I have a lot of stuff in there.
So I am also trying to autoload everything possible that is currently "required" by my emacs.el.
I have a module that exposes 12 entry points - interactive functions I can call.
Is the correct approach to have 12 calls to autoload in order to insure that the module is loaded regardless of which function I call? Are there any problems with this approach? Will it present performance issues?
If not that approach, then what?
What you really want is to get the autoloads generated for you automatically, so that your .emacs file remains pristine. Most packages have the ;;;###autoload lines in them already, and if not, you can easily add them.
To manage this, you can put all the packages in a directory, say ~/emacs/lisp, and in there have a file named update-auto-loads.el which contains:
;; put this path into the load-path automatically
;;;###autoload
(progn
(setq load-path (cons (file-name-directory load-file-name) load-path)))
;;;###autoload
(defun update-autoloads-in-package-area (&optional file)
"Update autoloads for files in the diretory containing this file."
(interactive)
(let ((base (file-truename
(file-name-directory
(symbol-file 'update-autoloads-in-package-area 'defun)))))
(require 'autoload) ;ironic, i know
(let ((generated-autoload-file (concat base "loaddefs.el")))
(when (not (file-exists-p generated-autoload-file))
(with-current-buffer (find-file-noselect generated-autoload-file)
(insert ";;") ;; create the file with non-zero size to appease autoload
(save-buffer)))
(cd base)
(if file
(update-file-autoloads file)
(update-autoloads-from-directories base)))))
;;;###autoload
(defun update-autoloads-for-file-in-package-area (file)
(interactive "f")
(update-autoloads-in-package-area file))
If you add 'update-autoloads-in-package-area to your kill-emacs-hook, then the loaddefs.el will automatically be updated every time you exit Emacs.
And, to tie it all together, add this to your .emacs:
(load-file "~/emacs/lisp/loaddefs.el")
Now, when you download a new package, just save it in the ~/emacs/lisp directory, update the loaddefs via M-x update-autoloads-in-package-area (or exit emacs), and it'll be available the next time you run Emacs. No more changes to your .emacs to load things.
See this question for other alternatives to speeding up Emacs startup: How can I make Emacs start-up faster?
Well, who cares how slowly it starts?
Fire it up via emacs --daemon & and then connect using either one of
emacsclient -c /some/file.ext, or
emacsclient -nw
I created aliases for both these as emx and emt, respectively. Continuing once editing session is so much saner...
Ideally you shouldn't have any load or require in your .emacs file.
You should be using autoload instead...
e.g.
(autoload 'slime-selector "slime" t)
You will need to use eval-after-load to do any library specific config, but the upshot is that you won't need to wait for all this to load up front, or cause errors on versions of Emacs that don't have the same functionality. (e.g. Terminal based, or a different platform etc.)
While this may not affect you right now, chances are, in future you will want to use the same config on all machines / environments where you use Emacs, so it's a very good thing to have your config ready to fly.
Also use (start-server) and open external files into Emacs using emacsclient - So you avoid restarting Emacs.

goto-file in Emacs

Is there a substitute in emacs for the vi "gf" command?
meaning try to open the file which is under the cursor right now
if a real file name is in fact there.
Thanks
You want the find-file-at-point function (which is also aliased to ffap). It's not bound to a key by default, but you can use
M-x ffap
Or, you can put in your .emacs file:
(ffap-bindings)
This will replace many of the normal find-file key bindings (like C-x C-f) with ffap-based versions. See the commentary in ffap.el for details.
Thanks, it works quite well but somehow the vi (gf) version is
still somewhat smarter. I think it looks at some path variable for search paths.
I made something which is needlessly complicated but works for me (only in linux).
It uses the "locate" command to search for the path under the cursor.
I guess it could be made smarter by searching the relative path to the current file first.
sorry for my bad elisp skills...It can probably be achieved in a much nicer way.
put in your .emacs, then use with M-x goto-file
(defun shell-command-to-string (command)
"Execute shell command COMMAND and return its output as a string."
(with-output-to-string
(with-current-buffer standard-output
(call-process shell-file-name nil t nil shell-command-switch command))))
(defun goto-file ()
"open file under cursor"
(interactive)
(find-file (shell-command-to-string (concat "locate " (current-word) "|head -c -1" )) ))