blob: 8ccad672b66dea36425b259b0a865e56b5da7a29 [file] [log] [blame] [edit]
#!/usr/bin/env tclsh
###############################################################################
# BRLTTY - A background process providing access to the console screen (when in
# text mode) for a blind person using a refreshable braille display.
#
# Copyright (C) 1995-2023 by The BRLTTY Developers.
#
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU Lesser General Public License, as published by the Free Software
# Foundation; either version 2.1 of the License, or (at your option) any
# later version. Please see the file LICENSE-LGPL for details.
#
# Web Page: http://brltty.app/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################
source [file join [file dirname [info script]] .. prologue.tcl]
cd $sourceRoot
proc getBuildDirectories {{root ""}} {
set directories [list]
if {[string length $root] == 0} {
set root .
set setPath {
set path $name
}
} else {
set setPath {
set path [file join $root $name]
}
}
if {[file exists [file join $root Makefile.in]]} {
lappend directories $root
}
foreach name [readdir $root] {
eval $setPath
set type [file type $path]
if {[string equal $type link]} {
continue
}
if {[string equal $type directory]} {
lvarcat directories [getBuildDirectories $path]
}
}
return $directories
}
proc generatedFile {file} {
set name [file tail $file]
if {[string equal [file extension [file rootname $name]] .auto]} {
return 1
}
if {[regexp {\.tab\.c$} $name]} {
return 1
}
if {[lcontain {brlapi_constants.h} $name]} {
return 1
}
return 0
}
proc sourceFile {file} {
set name [lindex [set components [file split $file]] end]
regsub {^forbuild(\.)} $name {config\1} name
set path [eval file join [lreplace $components end end "$name.in"]]
if {[file exists $path]} {
return $path
}
return ""
}
proc dependencyExists {file} {
if {[file exists $file]} {
return 1
}
if {[string length [set source [sourceFile $file]]] > 0} {
if {[file exists $source]} {
return 1
}
}
return 0
}
proc getDependencies {file} {
upvar #0 dependencies($file) dependencies
if {![info exists dependencies]} {
lappend dependencies $file
if {[string length [set source [sourceFile $file]]] == 0} {
set source $file
}
set stream [open $source {RDONLY}]
set includes [list]
while {[gets $stream line] >= 0} {
if {[regexp {^ *# *include *"([^"]*)"} $line x header]} {
lappend includes $header
}
}
close $stream; unset stream
if {[string equal [set directory [file dirname $file]] .]} {
set directory ""
}
foreach include $includes {
if {[generatedFile $include]} {
if {[string first / $include] < 0} {
set include [file join $directory $include]
}
lappend dependencies $include
} else {
set found 0
foreach location [list $directory Programs Headers ""] {
if {[dependencyExists [set path [file join $location $include]]]} {
lvarcat dependencies [lindex [intersect3 $dependencies [getDependencies $path]] 2]
set found 1
break
}
}
if {!$found} {
writeProgramMessage "missing dependency: $file includes $include"
}
}
}
}
return $dependencies
}
set optionDefinitions {
}
processProgramArguments optionValues $optionDefinitions
set sourceExtensions {c cc y}
set sourceExtensionsGlob "{[join $sourceExtensions ,]}"
foreach buildDirectory [set buildDirectories [getBuildDirectories]] {
foreach sourceFile [glob -nocomplain [file join $buildDirectory "*.$sourceExtensionsGlob"]] {
regsub {^(\./)+} $sourceFile {} sourceFile
if {![generatedFile $sourceFile]} {
lappend sourceFiles($buildDirectory) $sourceFile
getDependencies $sourceFile
}
}
}
set generatedDependencies [list]
set objectFiles [list]
set absoluteStream [open absdeps.mk {WRONLY CREAT TRUNC}]
foreach buildDirectory [lsort $buildDirectories] {
set relativeStream [open [file join $buildDirectory reldeps.mk] {WRONLY CREAT TRUNC}]
if {[info exists sourceFiles($buildDirectory)]} {
foreach sourceFile [lsort $sourceFiles($buildDirectory)] {
switch -exact -- [file extension $sourceFile] {
".y" {
set objectExtension ".tab.c"
}
default {
set objectExtension ".\$O"
}
}
set objectFile "[file rootname $sourceFile]$objectExtension"
set objectName [file tail $objectFile]
puts $absoluteStream "# Dependencies for $objectFile:"
puts $relativeStream "# Dependencies for $objectName:"
lappend objectFiles $objectFile
foreach dependency $dependencies($sourceFile) {
if {[set generated [generatedFile $dependency]]} {
lappend generatedDependencies $dependency
}
if {$generated || ([string length [sourceFile $dependency]] > 0)} {
set tree BLD
} else {
set tree SRC
}
puts $absoluteStream "\$(BLD_TOP)$objectFile: \$(${tree}_TOP)$dependency"
puts -nonewline $relativeStream "$objectName: "
if {[string equal $buildDirectory [file dirname $dependency]]} {
if {![string equal $tree BLD]} {
puts -nonewline $relativeStream "\$(${tree}_DIR)/"
}
puts $relativeStream [file tail $dependency]
} else {
puts $relativeStream "\$(${tree}_TOP)$dependency"
}
}
puts $absoluteStream "\tcd \$(@D) && \$(MAKE) \$(@F)"
puts $absoluteStream ""
puts $relativeStream ""
}
}
close $relativeStream; unset relativeStream
}
if {![lempty [set generatedDependencies [lindex [intersect3 [lrmdups $generatedDependencies] $objectFiles] 0]]]} {
puts $absoluteStream "# Generated dependencies:"
foreach dependency [lsort $generatedDependencies] {
puts $absoluteStream "\$(BLD_TOP)$dependency:"
puts $absoluteStream "\tcd \$(@D) && \$(MAKE) \$(@F)"
}
puts $absoluteStream ""
}
close $absoluteStream; unset absoluteStream
exit 0