qt-light/chicken-compile-qt-extensio...

208 lines
6.1 KiB
Scheme
Executable File

#!/bin/sh
#|
exec "$CHICKEN_CSI" -s "$0" "$@"
|#
;; chicken-compile-qt-extension.scm
(module main ()
(import scheme
(chicken base)
(chicken condition)
(chicken file)
(chicken file posix)
(chicken foreign)
(chicken format)
(chicken pathname)
(chicken platform)
(chicken process)
(chicken process-context)
(chicken string)
regex
shell
srfi-1)
(define setup-verbose-mode (make-parameter #f))
(define run-verbose (make-parameter #f))
(define (quit fstr . args)
(flush-output)
(fprintf (current-error-port) "~?~%" fstr args)
(exit 1))
(define (file-execute-access? p)
(and (file-exists? p)
(file-readable? p)
(file-executable? p)))
(define CMAKE_PATH
(or (get-environment-variable "CMAKE_PATH")
(and (file-execute-access? "/usr/bin/cmake") "/usr/bin/cmake")
(and (file-execute-access? "/usr/local/bin/cmake") "/usr/local/bin/cmake")
(quit "please set the CMAKE_PATH environment variable") ) )
(define (chicken-prefix)
(let ((csc-path (get-environment-variable "CHICKEN_CSC")))
(let-values (((_ _ dir-elems) (decompose-directory csc-path)))
(pathname-directory (make-absolute-pathname (drop-right dir-elems 2) "csc")))))
(define prefix (chicken-prefix))
(define libpath (make-pathname prefix "lib"))
(define incpath (make-pathname prefix "include"))
(define cincpath (make-pathname incpath "chicken"))
(define binpath (make-pathname prefix "bin"))
(define csc (make-pathname binpath "csc"))
(define keepfiles #f)
(define cmake CMAKE_PATH)
(define mingw32 (eq? (build-platform) 'mingw32))
(define macosx (eq? (software-version) 'macosx))
(define outfile #f)
(define install_name_tool
(and macosx
"/usr/bin/install_name_tool"))
(define gmake
(cond ((memq (software-version) '(freebsd netbsd openbsd))
"gmake")
(mingw32 "mingw32-make")
(else "make")))
(define options-with-arguments
'("-debug" "-output-file" "-heap-size" "-nursery" "-stack-size" "-compiler"
"-unit" "-uses" "-keyword-style" "-optimize-level" "-include-path"
"-database-size" "-extend" "-prelude" "-postlude" "-prologue" "-epilogue"
"-inline-limit" "-profile-name" "-emit-inline-file"
"-feature" "-debug-level" "-consult-types-file" "-no-feature"
"-consult-inline-file" "-emit-import-library" "-module" "-link"
"-D" "-K" "-X" "-j" "-I" "-o" "-R" "-C" "-L" "-emit-link-file"
"-unroll-limit" "-types"))
(define (filter-options args)
(let loop ((args args) (opts '()) (files '()))
(if (null? args)
(values (reverse opts) (reverse files))
(let ((arg (car args))
(more (cdr args)))
(cond ((string=? "-k" arg) (set! keepfiles #t))
((string=? "-v" arg)
(setup-verbose-mode #t)
(run-verbose #t))
((member arg '("--help" "-h" "-help"))
(run (csc -h)))
((and (string=? "-o" arg) (pair? more))
(set! outfile (car more))))
(if (and (> (string-length arg) 1)
(char=? #\- (string-ref arg 0)))
(if (member arg options-with-arguments)
(if (null? more)
(loop more (cons arg opts) files)
(loop (cdr more) (cons* (car more) arg opts) files))
(loop more (cons arg opts) files))
(loop more opts (cons arg files)))))))
(define (qs* string)
(conc #\" (string-substitute "\"" "\\\"" string) #\"))
(define (compile-qt-extension cppfiles hfiles)
(let* ((cppfile (car cppfiles))
(build-dir (or (pathname-directory cppfile) "./"))
(cmakelists (make-pathname build-dir "CMakeLists.txt"))
(name (pathname-file cppfile))
(mkfile (qs (make-pathname build-dir "Makefile")))
(output (or outfile (make-pathname #f name "so"))))
(with-output-to-file cmakelists
(lambda ()
(let ((csc (qs (normalize-pathname csc)))
(libdir (qs* (normalize-pathname libpath)))
(incdir (qs* (normalize-pathname incpath)))
(cincdir (qs* (normalize-pathname cincpath))))
(print
#<#EOF
cmake_minimum_required(VERSION 3.16.0)
project(qt-light VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 COMPONENTS Core REQUIRED)
find_package(Qt6 COMPONENTS Multimedia REQUIRED)
find_package(Qt6 COMPONENTS Widgets REQUIRED)
find_package(Qt6 COMPONENTS UiTools REQUIRED)
add_library(#{name} SHARED
#{(string-intersperse cppfiles)}
)
target_include_directories(#{name} PRIVATE #{incdir} #{cincdir})
target_link_directories(#{name} PRIVATE #{libdir})
target_link_libraries(#{name} PRIVATE Qt6::Core Qt6::Multimedia Qt6::Widgets Qt6::UiTools)
EOF
) ) ))
(run (,cmake ,build-dir))
(delete-file* output)
(display mkfile)
(run (,gmake -f ,mkfile clean ,(if mingw32 "release" "all")))
(cp
(make-pathname
(if mingw32 "release" #f)
(if mingw32 name (string-append "lib" name))
(cond (mingw32 "dll")
(macosx ".dylib")
(else ".so")))
output)
(when macosx
(run (,install_name_tool -change "libchicken.dylib" ,(make-pathname libpath "libchicken" "dylib") ,output)))
) )
(define (rm-f . files)
(for-each
(lambda (fname)
(when (setup-verbose-mode) (print " rm -f " (qs fname)))
(delete-file* fname))
files))
(define (cp from to)
(when (setup-verbose-mode)
(print " cp " (qs from) " " (qs to)))
(copy-file from to))
(define (main args)
(let-values (((opts files) (filter-options args)))
(let ((cppfiles
(filter-map
(lambda (fname)
(let ((ext (pathname-extension fname)))
(cond ((member ext '("scm" "ss"))
(run ("csc" ,fname "-t" "-c++" ,@opts))
(pathname-replace-extension fname "cpp"))
((member ext '("cxx" "c++" "cpp"))
fname)
(else #f))))
files))
(hfiles
(filter
(lambda (fname)
(let ((ext (pathname-extension fname)))
(member ext '("h" "hpp"))))
files)))
(if (null? cppfiles)
(quit "no Scheme or C++ files to process")
(handle-exceptions ex
(begin
(flush-output)
(print-error-message ex (current-error-port))
(exit 1))
(compile-qt-extension (append cppfiles (list "main.cpp")) hfiles))))))
(main (command-line-arguments))
)