(I use scons, but the principle is the same. Change SConstruct to Makefile and scons to make...)
I've customized by .emacs so that it always compiles the project containing the current buffer's file, however deeply nested; it searches upwards for the first SConstruct and uses that as it's project root directory.
Here's a couple of functions which search up the directory hierarchy looking for SConstruct.
;; inspired by jds-find-tags-file in http://www.emacswiki.org/emacs/EmacsTags
(defun find-sconstruct ()
"recursively searches upwards from buffer's current dir for file named SConstruct and returns that dir. Or nil if not found or if buffer is not visiting a file"
(labels
((find-sconstruct-r (path)
(let* ((parent (file-name-directory path))
(possible-file (concat parent "SConstruct")))
(cond
((file-exists-p possible-file)
(throw 'found-it possible-file))
((string= "/SConstruct" possible-file)
(error "No SConstruct found"))
(t (find-sconstruct-r (directory-file-name parent)))))))
(if (buffer-file-name)
(catch 'found-it
(find-sconstruct-r (buffer-file-name)))
(error "Buffer is not visiting a file"))))
(defun project-root ()
(file-name-directory (find-sconstruct)))
You can then change your compile-command
to use project-root
e.g.
(concat "cd " (project-root) " && scons")