Tcl Extension Architecture (TEA) Sample Extension

Check-in [9b70b161ae]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2018 Conference, Houston/TX, US, Oct 15-19
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Aug 20.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improvements to the practcl project builder. Added a new facility to pull authors from Changelog
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | practcl
Files: files | file ages | folders
SHA3-256:9b70b161ae12e844d0bc35720c8a2e3a4c8ee98920cb01e25090687b4a3c6c7c
User & Date: seandeelywoods 2018-01-25 18:33:55
Context
2018-01-25
18:33
Improvements to the practcl project builder. Added a new facility to pull authors from Changelog Leaf check-in: 9b70b161ae user: seandeelywoods tags: practcl
2018-01-18
00:32
Updated TEA

Added a "teapot" build target as a reference example check-in: 746f2b387e user: seandeelywoods tags: practcl

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.





1
2
3
4
5
6
7




2015-08-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* configure:          Rfe [00189c4afc]: Allow semi-static UCRT build on
	* win/makefile.vc     Windows with VC 14.0
	* win/rules.vc

2013-07-04  Jan Nijtmans <nijtmans@users.sf.net>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
2018-01-19  Sean Woods    <yoda@etoyoc.com>

    * Rewrote build system to use practcl

2015-08-28  Jan Nijtmans  <nijtmans@users.sf.net>

	* configure:          Rfe [00189c4afc]: Allow semi-static UCRT build on
	* win/makefile.vc     Windows with VC 14.0
	* win/rules.vc

2013-07-04  Jan Nijtmans <nijtmans@users.sf.net>

Changes to make.tcl.

9
10
11
12
13
14
15
16
17








18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55






56
57
58
59
60

61

62
63
64












65
66

67





68























69







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
...
178
179
180
181
182
183
184
185
186
187


188


189
190
191

192
193


194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
  source [file join $SRCDIR tclconfig practcl.tcl]
}

array set ::project [::practcl::config.tcl $CWD]
::practcl::library create LIBRARY [array get ::project]
LIBRARY define set builddir $CWD
LIBRARY define set srcdir $SRCDIR
LIBRARY define set author {{Tcl Core}}
LIBRARY define set license BSD








LIBRARY add [file join $::SRCDIR generic sample.c]
LIBRARY add [file join $::SRCDIR generic sample.tcl]
LIBRARY define add public-verbatim [file join $::SRCDIR generic sample.h]

if {![LIBRARY define exists TCL_SRC_DIR]} {
  # Did not detect the Tcl source directory. Run autoconf
  ::practcl::doexec sh [file join $::SRCDIR configure]
  array set ::project [::practcl::config.tcl $CWD]
  LIBRARY define set [array get ::project]
}
###
# Create build targets
###
LIBRARY target add implement {
  filename sample.c
} {
  LIBRARY go
  LIBRARY implement $::project(builddir)
  set fout [open pkgIndex.tcl w]
  puts $fout "
  #
  # Tcl package index file
  #
  "
  puts $fout [LIBRARY package-ifneeded]
  close $fout

  if {![file exists make.tcl]} {
    set fout [open make.tcl w]
    puts $fout "# Redirect to the make file that lives in the project's source dir"
    puts $fout [list source [file join $::SRCDIR make.tcl]]
    close $fout
    if {$::tcl_platform(platform)!="windows"} {
      file attributes -permission a+x make.tcl
    }
  }
}

LIBRARY target add all {






  aliases {binaries libraries}
  depends library
}

LIBRARY target add library {

  aliases {all libraries}

  triggers implement
  filename [LIBRARY define get libfile]
} {












  puts "BUILDING [my define get libfile]"
  my build-library [my define get libfile] [self]

}





























switch [lindex $argv 0] {







  install {
    if {[info exists ::env(DESTDIR)]} {
      set DESTDIR $::env(DESTDIR)
    }
    LIBRARY target depends library doc
    LIBRARY target do
    if {[llength $argv]>1} {
      set DESTDIR [file normalize [string trimright [lindex $argv 1]]]
    }
    set dat [LIBRARY target pkginfo]
    dict with dat {}
    if {$DESTDIR ne {}} {
      foreach path {
        includedir
        mandir
        datadir
        libdir
................................................................................
      ::practcl::copyDir [LIBRARY define get output_tcl] $pkglibdir
    }
  }
  install-package {
    if {[llength $argv]<1} {
      error "Usage: install DESTINATION"
    }
    LIBRARY target depends library doc
    LIBRARY target do
    set dat [LIBRARY target pkginfo]
    dict with dat {}
    set pkglibdir [file join [lindex $argv 1] $PKG_DIR]
    #========================================================================
    # Install binary object libraries.  On Windows this includes both .dll and
    # .lib files.  Because the .lib files are not explicitly listed anywhere,
    # we need to deduce their existence from the .dll file of the same name.
    # Library files go into the lib directory.
................................................................................
      ::practcl::copyDir $file $pkglibdir
    }
    ::practcl::copyDir pkgIndex.tcl $pkglibdir
    if {[LIBRARY define get output_tcl] ne {}} {
      ::practcl::copyDir [LIBRARY define get output_tcl] $pkglibdir
    }
  }
  info {
    set dat [LIBRARY target pkginfo]
    foreach {field value} $dat {
      puts [list $field: $value]
    }
    exit 0
  }
  teapot {
    LIBRARY target depends library doc
    LIBRARY target do
    set dat [LIBRARY target pkginfo]
    dict with dat {}
    set teapotvfs [file join $CWD teapot.vfs]
    if {[file exists $teapotvfs]} {
      file delete -force $teapotvfs
    }
    file mkdir $teapotvfs
    file copy -force [LIBRARY define get libfile] $teapotvfs
................................................................................
    }
    ###
    # Generate the teapot meta file
    ###
    set fout [open [file join $teapotvfs teapot.txt] w]
    puts $fout [list Package $name $version]
    puts $fout [list Meta platform [LIBRARY define get TEACUP_PROFILE]]
    foreach field {
      description license platform subject summary
    } {


      if {[dict exists $dat $field]} {


        puts $fout [list Meta $field [dict get $dat $field]]
      }
    }

    foreach field {
      author category require


    } {
      if {[dict exists $dat $field]} {
        foreach entry [dict get $dat $field] {

          puts $fout [list Meta $field $entry]
        }
      }
    }
    close $fout
    ::practcl::tcllib_require zipfile::mkzip
    ::zipfile::mkzip::mkzip ${name}-${version}-[LIBRARY define get TEACUP_PROFILE].zip -directory $teapotvfs
  }
  default {
    LIBRARY target trigger {*}$argv
    LIBRARY target do
  }
}







<
|
>
>
>
>
>
>
>
>









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>



|







<
>
>
>
>
>
>




<
>
|
>

|

>
>
>
>
>
>
>
>
>
>
>
>

<
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>




|
|



|







 







|
|
|







 







<
<
<
<
<
<
<

|
|
|







 







|
|
|
>
>
|
>
>
|
|
|
>
|
<
>
>
|
<
<
>
|





|


|
|


9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

















34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
191
192
193
194
195
196
197







198
199
200
201
202
203
204
205
206
207
208
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

235
236
237


238
239
240
241
242
243
244
245
246
247
248
249
250
251
  source [file join $SRCDIR tclconfig practcl.tcl]
}

array set ::project [::practcl::config.tcl $CWD]
::practcl::library create LIBRARY [array get ::project]
LIBRARY define set builddir $CWD
LIBRARY define set srcdir $SRCDIR

LIBRARY meta set license BSD
LIBRARY meta set description {The Reference TEA Extension for Developers}
###
# Generate List of Authors
###
foreach match [::practcl::grep \<.*\@ [file join $SRCDIR ChangeLog]] {
  LIBRARY meta add authors [lrange $match 1 end]
}

LIBRARY add [file join $::SRCDIR generic sample.c]
LIBRARY add [file join $::SRCDIR generic sample.tcl]
LIBRARY define add public-verbatim [file join $::SRCDIR generic sample.h]

if {![LIBRARY define exists TCL_SRC_DIR]} {
  # Did not detect the Tcl source directory. Run autoconf
  ::practcl::doexec sh [file join $::SRCDIR configure]
  array set ::project [::practcl::config.tcl $CWD]
  LIBRARY define set [array get ::project]

















  # Generate a make.tcl in this directory
  if {![file exists make.tcl]} {
    set fout [open make.tcl w]
    puts $fout "# Redirect to the make file that lives in the project's source dir"
    puts $fout [list source [file join $srcdir make.tcl]]
    close $fout
    if {$::tcl_platform(platform)!="windows"} {
      file attributes -permission a+x make.tcl
    }
  }
}


###
# Create build targets
###

# Virtual target to mimic the behavior of "make all"
LIBRARY make target all {
  aliases {binaries libraries}
  depends library
}



# Generate the dynamic library and pkgIndex.tcl
LIBRARY make target library {
  triggers implement
  files {sample.c sample.h pkgIndex.tcl [LIBRARY define get libfile]}
} {
  # Collect configuration
  my go
  
  ##
  # Generate dynamic C files
  ##
  set builddir [my define get builddir]
  my implement $builddir

  ###
  # Compile the library
  ###
  puts "BUILDING [my define get libfile]"

  my build-library [file join $builddir [my define get libfile]] [self]
  
  ##
  # Generate pkgIndex.tcl
  ##
  set fout [open [file join $builddir pkgIndex.tcl] w]
  puts $fout "
#
# Tcl package index file
#
  "
  puts $fout [my package-ifneeded]
  close $fout
}

if {"clean" in $argv} {
  # Clean is a little weird because it screws with dependencies
  # We do it as a separate action
  foreach {name obj} [LIBRARY make objects] {
    set files [$obj output]
    foreach file $files {
      file delete -force [file join $CWD $file]
    }
  }
  foreach pattern {*.lib *.zip *.vfs objs/*} {
    foreach file [glob -nocomplain [file join $CWD $file]] {
      file delete -force $pattern
    }
  }
}

switch [lindex $argv 0] {
  info {
    set dat [LIBRARY make pkginfo]
    foreach {field value} $dat {
      puts [list $field: $value]
    }
    exit 0
  }
  install {
    if {[info exists ::env(DESTDIR)]} {
      set DESTDIR $::env(DESTDIR)
    }
    LIBRARY make depends library doc
    LIBRARY make do
    if {[llength $argv]>1} {
      set DESTDIR [file normalize [string trimright [lindex $argv 1]]]
    }
    set dat [LIBRARY make pkginfo]
    dict with dat {}
    if {$DESTDIR ne {}} {
      foreach path {
        includedir
        mandir
        datadir
        libdir
................................................................................
      ::practcl::copyDir [LIBRARY define get output_tcl] $pkglibdir
    }
  }
  install-package {
    if {[llength $argv]<1} {
      error "Usage: install DESTINATION"
    }
    LIBRARY make depends library doc
    LIBRARY make do
    set dat [LIBRARY make pkginfo]
    dict with dat {}
    set pkglibdir [file join [lindex $argv 1] $PKG_DIR]
    #========================================================================
    # Install binary object libraries.  On Windows this includes both .dll and
    # .lib files.  Because the .lib files are not explicitly listed anywhere,
    # we need to deduce their existence from the .dll file of the same name.
    # Library files go into the lib directory.
................................................................................
      ::practcl::copyDir $file $pkglibdir
    }
    ::practcl::copyDir pkgIndex.tcl $pkglibdir
    if {[LIBRARY define get output_tcl] ne {}} {
      ::practcl::copyDir [LIBRARY define get output_tcl] $pkglibdir
    }
  }







  teapot {
    LIBRARY make depends library doc
    LIBRARY make do
    set dat [LIBRARY make pkginfo]
    dict with dat {}
    set teapotvfs [file join $CWD teapot.vfs]
    if {[file exists $teapotvfs]} {
      file delete -force $teapotvfs
    }
    file mkdir $teapotvfs
    file copy -force [LIBRARY define get libfile] $teapotvfs
................................................................................
    }
    ###
    # Generate the teapot meta file
    ###
    set fout [open [file join $teapotvfs teapot.txt] w]
    puts $fout [list Package $name $version]
    puts $fout [list Meta platform [LIBRARY define get TEACUP_PROFILE]]
    puts $fout [list Meta practcl::build_date [clock format [file mtime [LIBRARY define get libfile]]]]
    # Pull SCM checkout info
    ::practcl::distribution select LIBRARY
    set info [LIBRARY scm_info]
    foreach item {scm hash isodate tags} {
      if {![dict exists $info $item]} continue
      set value [dict get $info $item]
      if {$value eq {}} continue     
      puts $fout [list Meta practcl::scm_$item $value]
    }

    set mdat [LIBRARY meta dump]
    foreach {field value} $mdat {

      if {[string index $field end] eq ":"} {
        puts $fout [list Meta [string trimright $field :] $value]
      } else {


        foreach item $value {
          puts $fout [list Meta $field $item]
        }
      }
    }
    close $fout
    ::practcl::tcllib_require zipfile::mkzip
    ::zipfile::mkzip::mkzip [dict get $dat zipfile] -directory $teapotvfs
  }
  default {
    LIBRARY make trigger {*}$argv
    LIBRARY make do
  }
}