compilationcommon-lispasdf

Using the :around-compile argument to asdf:defsystem


To better understand how :around-compile works, I would like to track (ie, printout) which component file is currently being compiled.

The ASDF Manual seems to imply that the value can be a lambda expression with one argument--eg, (lambda (next) ... (funcall next ...) ...)--which will call ASDF's compile-file* function, which can take the arguments (input-file &rest keys &key compile-check output-file warnings-file emit-cfasl &allow-other-keys). The Manual also says the around-compile hook may supply additional keyword arguments to pass to that call to compile-file*, which I assume refers to items like the input-file. Is it available from next? For example, a simple case might do something like:

(defsystem :project
  ...
  :around-compile (lambda (next)
                    (format t "~&Compiling ~A" input-file)
                    (funcall next))
  ...)

Is this on the right track? And could this also be done with the :perform keyword? Thanks for any insights.


Solution

  • This is something that would work (thunk corresponds to your next):

    (asdf:defsystem "$PROJECT_NAME"
      :description "A simple ASDF system with custom compilation messages"
      :version "0.1"
      :serial t
      :components ((:file "src/file1")
                   (:file "src/file2"))
      :around-compile (lambda (thunk)
                        ;; Before compilation
                        (format t "Doing something before compilation..")
                          (let ((result (funcall thunk)))
                            ;; After compilation
                            (format t "Doing something after compilation.. ~A~%" result)
                            result)))
    

    This bash script generates my-system, an example package.

    You need uiop::*compile-file-pathname* to be able to refer to the compiled file's path.

    I left out the part which would actually tell asdf to use the current folder as a project folder. Therefore, you have to generate this bash script only within your ~/quicklisp/local-projects/ folder, so that asdf can easily find the project for loading.

    Therefore you do:

    cd ~/quicklisp/local-projects/
    nano build-my-system.sh
    

    and enter as its content:

    #!/bin/bash
    
    # Define the project name and directory
    PROJECT_NAME="my-system"
    PROJECT_DIR="$(pwd)/$PROJECT_NAME"
    
    # Create the directory structure
    echo "Creating directory structure..."
    mkdir -p "$PROJECT_DIR/src"
    
    # Create the system definition file (my-system.asd)
    echo "Creating $PROJECT_NAME.asd..."
    cat <<EOF > "$PROJECT_DIR/$PROJECT_NAME.asd"
    (asdf:defsystem "$PROJECT_NAME"
      :description "A simple ASDF system with custom compilation messages"
      :version "0.1"
      :serial t
      :components ((:file "src/file1")
                   (:file "src/file2"))
      :around-compile (lambda (thunk)
                        ;; Before compilation
                        (format t "Doing something before compilation..")
                          (let ((result (funcall thunk)))
                            ;; After compilation
                            (format t "Doing something after compilation.. ~A~%" result)
                            result)))
    EOF
    
    # Create source file 1 (src/file1.lisp)
    echo "Creating src/file1.lisp..."
    cat <<EOF > "$PROJECT_DIR/src/file1.lisp"
    (defun hello ()
      (format t "Hello from file1!~%"))
    EOF
    
    # Create source file 2 (src/file2.lisp)
    echo "Creating src/file2.lisp..."
    cat <<EOF > "$PROJECT_DIR/src/file2.lisp"
    (defun goodbye ()
      (format t "Goodbye from file2!~%"))
    EOF
    
    # Create a README.md file (optional)
    echo "Creating README.md..."
    cat <<EOF > "$PROJECT_DIR/README.md"
    # My System
    
    This is a simple Common Lisp system with custom compile-time messages using ASDF.
    EOF
    
    
    # Build the system using SBCL
    echo "Building the system with SBCL..."
    sbcl --eval "(asdf:load-system \"$PROJECT_NAME\")" --eval "(hello)" --eval "(goodbye)" --quit
    
    echo "Build complete!"
    

    and run the script with:

    bash build-my-system.sh
    

    And then it will generate my-system with its folder and files with lisp code.

    And it will run sbcl and load my-system.

    output:

    % bash build-my-system.sh
    Creating directory structure...
    Creating my-system.asd...
    Creating src/file1.lisp...
    Creating src/file2.lisp...
    Creating README.md...
    Building the system with SBCL...
    This is SBCL 2.4.6, an implementation of ANSI Common Lisp.
    More information about SBCL is available at <http://www.sbcl.org/>.
    
    SBCL is free software, provided as is, with absolutely no warranty.
    It is mostly in the public domain; some portions are provided under
    BSD-style licenses.  See the CREDITS and COPYING files in the
    distribution for more information.
    Loading ~/.sbclrc...
    Doing something before compilation..
    ; compiling file "/Users/josephus/quicklisp/local-projects/my-system/src/file1.lisp" (written 19 OCT 2024 08:16:17 AM):
    
    ; wrote /Users/josephus/.cache/common-lisp/sbcl-2.4.6-macosx-arm64/Users/josephus/quicklisp/local-projects/my-system/src/file1-tmpGHU3ALSV.fasl
    ; compilation finished in 0:00:00.000
    Doing something after compilation.. /Users/josephus/.cache/common-lisp/sbcl-2.4.6-macosx-arm64/Users/josephus/quicklisp/local-projects/my-system/src/file1.fasl
    Doing something before compilation..
    ; compiling file "/Users/josephus/quicklisp/local-projects/my-system/src/file2.lisp" (written 19 OCT 2024 08:16:17 AM):
    
    ; wrote /Users/josephus/.cache/common-lisp/sbcl-2.4.6-macosx-arm64/Users/josephus/quicklisp/local-projects/my-system/src/file2-tmpAAURSO1.fasl
    ; compilation finished in 0:00:00.000
    Doing something after compilation.. /Users/josephus/.cache/common-lisp/sbcl-2.4.6-macosx-arm64/Users/josephus/quicklisp/local-projects/my-system/src/file2.fasl
    Hello from file1!
    Goodbye from file2!
    Build complete!
    

    For windows users, you create a powershell file within your quicklisp/local-projects/ folder with the filename: build-my-system.ps1

    # Define the project name and directory
    $ProjectName = "my-system"
    $ProjectDir = Join-Path (Get-Location) $ProjectName
    
    # Create the directory structure
    Write-Host "Creating directory structure..."
    New-Item -ItemType Directory -Path "$ProjectDir\src" -Force
    
    # Create the system definition file (my-system.asd)
    Write-Host "Creating $ProjectName.asd..."
    @"
    (asdf:defsystem "$PROJECT_NAME"
      :description "A simple ASDF system with custom compilation messages"
      :version "0.1"
      :serial t
      :components ((:file "src/file1")
                   (:file "src/file2"))
      :around-compile (lambda (thunk)
                        ;; Before compilation
                        (format t "Doing something before compilation..")
                          (let ((result (funcall thunk)))
                            ;; After compilation
                            (format t "Doing something after compilation.. ~A~%" result)
                            result)))
    "@ | Out-File "$ProjectDir\$ProjectName.asd" -Encoding UTF8
    
    # Create source file 1 (src/file1.lisp)
    Write-Host "Creating src/file1.lisp..."
    @"
    (defun hello ()
      (format t "Hello from file1!~%"))
    "@ | Out-File "$ProjectDir\src\file1.lisp" -Encoding UTF8
    
    # Create source file 2 (src/file2.lisp)
    Write-Host "Creating src/file2.lisp..."
    @"
    (defun goodbye ()
      (format t "Goodbye from file2!~%"))
    "@ | Out-File "$ProjectDir\src\file2.lisp" -Encoding UTF8
    
    # Create a README.md file (optional)
    Write-Host "Creating README.md..."
    @"
    # My System
    
    This is a simple Common Lisp system with custom compile-time messages using ASDF.
    "@ | Out-File "$ProjectDir\README.md" -Encoding UTF8
    
    # Build the system using SBCL
    Write-Host "Building the system with SBCL..."
    sbcl --eval "(asdf:load-system \"$ProjectName\")" --eval "(hello)" --eval "(goodbye)" --quit
    
    Write-Host "Build complete!"
    

    and run it from there with:

    ./build-my-system.ps1
    

    I hope this works, because I didn't test the windows powershell script. But the bash scripts worked on my mac.