If you often edit source code residing in subdirectories relative to your Makefile, you can use this to directly (re)build:

(defun get-above-makefile ()
  (let ((dir (locate-dominating-file "." "Makefile")))
    (when dir
      (concat dir "Makefile"))))

;; bind compiling with get-above-makefile to f5
(global-set-key [f5] (lambda () (interactive) (compile (format
	   "make -f %s" (get-above-makefile)))))

The codes below is an alternative, and you can use the list to find multiple filename format.

(setq compilation-filenames '("Makefile" "makefile"))

(defun get-nearest-compilation-file ()
  "Search for the compilation file traversing up the directory tree."
  (let ((dir default-directory)
	(parent-dir (file-name-directory (directory-file-name default-directory)))
	(nearest-compilation-file 'nil))
    (while (and (not (string= dir parent-dir))
		(not nearest-compilation-file))
      (dolist (filename compilation-filenames)
	(setq file-path (concat dir filename))
	(when (file-readable-p file-path)
	  (setq nearest-compilation-file file-path)))
      (setq dir parent-dir
	    parent-dir (file-name-directory (directory-file-name parent-dir))))

live long and prosper – from zigler