main.rkt
#lang racket/base

(require dynext/compile dynext/link dynext/file racket/file srfi/8)

(define (older-than a b)
   (<
    (file-or-directory-modify-seconds a)
    (file-or-directory-modify-seconds b)))

(define (depending-on what deps make)
   (when (not
          (and (file-exists? what)
               (andmap
                (λ (dep)
                  (when (not (file-exists? dep))
                    (error "Dependancy not found" dep))
                  (older-than dep what))
                deps)))
     (make what deps))
   what)

(define (maybe-build-path a b) (if (absolute-path? b) b (build-path a b)))

(define (get-libname location name)
   (define libdir
     (build-path
      (if (eq? location 'relative) "." location)
      "compiled"
      "native"
      (system-library-subpath)))
   (when (not (directory-exists? libdir)) (make-directory* libdir))
   (build-path libdir (append-extension-suffix (string-append name "_ss"))))

(define (append-object-suffix-and-compiled source)
  (receive (base name is-dir?) (split-path source)
    (let ((cbase (build-path base "compiled")))
      (when (not (directory-exists? cbase))
         (make-directory cbase))
      (build-path cbase (append-object-suffix name)))))

(define (library location name . sources)
   (let ((objects
          (map
           (λ (source)
             (let ((source (maybe-build-path location source)))
               (depending-on
                (append-object-suffix-and-compiled source)
                (list source)
                (λ (object deps)
                  (compile-extension #f (car deps) object null)))))
           (filter
            (λ (i)
              (regexp-match
               #rx"\\.c(?:c(?:pp)?)?$"
               (path->string (build-path i))))
            sources))))
     (depending-on
      (get-libname location name)
      objects
      (λ (lib objects) (link-extension #f objects lib))))
   (void))

(provide depending-on library older-than)