Last update of this Page:
core
file and editor
backup files with ``tmk clean''
.``tmk tags''
.
convert
.
$HOME/.tmk/site-config/site-config.tmk
I found this is quite useful. Because you can read system wide configuration file first, and then this file override the setting.
tmk -sysinfo
tmk -reconfig
I want to delete core
file and editor backup file with
``tmk clean''
.
Add next code at your TMakefile (or TMakefile.proj). (Ref:: ``tmk
tutorial'', Chapter 3, Target clean) In this example, backup file name
is assumed as *~
like Emacs.
# # core and backup clean # target core_bk_clean ALWAYS_BUILD { set deletebakupfile [glob -nocomplain *~] append deletebakupfile " core a.out TAGS" puts -nonewline "file delete -- " foreach f ${deletebakupfile} { file delete -force -- ${f} puts -nonewline "${f} " } puts "" } depend clean core_bk_clean
``tmk
tags''
.Use module tags
.
And type % tmk tags
module { tags }
convert
.Here is a way to convert all *.png files to to *.eps with tmk and convert.
Sometimes, I want to convert files with convert
command
like next Makefile.
# -- Makefile -- .png.eps: convert $< $*.eps .SUFFIXES .png .eps
Next is such code, but depends on convert
command.
# # make_convert_rule with listed files # proc make_convert_rule { orig_suffix target_suffix file_list } { puts "make_suffix_rule: from $orig_suffix -> $target_suffix with $file_list" foreach one_source $file_list { if { [regsub $orig_suffix $one_source $target_suffix tmp] } { target $tmp $one_source { cmd convert ${SRC} ${TAIL} } build $tmp } else { puts "$one_source is no suffix $orig_suffix, ignored." } } } # # all files # proc make_convert_rule { orig_suffix target_suffix } { set allfile [glob -nocomplain "*$orig_suffix" ] make_convert_rule_with_list $orig_suffix $target_suffix $allfile }
If you want to convert some specified file like a.png, b.png and c.png to a.eps, b.eps and c.eps, next line will help you.
make_convert_rule_with_list .png .eps { a.png b.png c.png }
However, in the tmk manner, you want to all *.png to *.eps, just say:
make_convert_rule .png .eps
But clean
is not so easy. I think you sometimes make
some file with special suffix like *.eps directory. Then just rm
*.eps
is very dangerous.
Write subdir
in your TMakefile.
Example 1
# proceed in all subdirs subdir [glob -nocomplain *]
Example 2
# proceed specified subdirs `foo' and `bar' subdir "foo bar"
Q: I commented out the main function, but tmk
detects that
main function and tries to generate an executable. Then fail the
compilation. How can I avoid that?
A: Most easy way is that Just delete main functions which you do not need anymorefrom your source or use other function name. However, usually I just want to comment it out.
tmk
detects main function by a regex. So, if you delete main
function by some macros, sometimes tmk
do not know that
the main function is deleted. Then, tmk
tries to generate
an executable. But main is gone in fact, then you fail the
compilation.
To avoid this, (for the C++ module (cxx)) write the next lines in your TMakefile.
# automatic main function detection is deactivated. set ::cxx::DETECT_EXE 0
However, this case, no executable will be generated in this directory. If you do not need to link some functions in a file (say foo.C). Write line next lines in your TMakefile.
# I do not want to compile this file. lappend EXCLUDE foo.C
Sometimes I want to remove an element from a list in project. To temporarily disable the someone's setting. For example, I want to remove an element -Wno-uninitialize from cxx::FLAGS. In such case, you can use this function:
# # delete with != # proc delete { element list } { set _delete_tmp "" while { [ llength $list ] > 0 } { # (car list) = [lrange $list 0 0] if { [lrange $list 0 0] != $element } { # puts "DEBUG: append [lrange $list 0 0]" lappend _delete_tmp [lrange $list 0 0] } # (cdr list) = [lrange $list 1 end] set list [lrange $list 1 end] } return $_delete_tmp }
Example of deleting the element -Wno-uninitialize from cxx::FLAGS is:
set cxx::FLAGS [ delete -Wno-uninitialize ${cxx::FLAGS} ]
When you have the next directory structure.
all_projdir +---+ GMU --- WidgetLib + myproj --- test1 -+-- myprog.C +-- TMakefile
And you want to build a program from myprog.C with GMU/WigetLib's library.
GMU/WigetLib should be build with tmk. Put next line to your
all_projdir/myproj/test1/TMakefile
.
#------------------------------------------------------------ # TMakefile #------------------------------------------------------------ lappend link::PROJLIBS GMU/WidgetLib
Then tmk knows the link name and the directories.
When you have the next directory structure.
/somedir +--- somewhere +--- project1 +--- lib1 +--- libproj1lib1.so | +--- include | +--- allmyproj +--- myproj +--- prog2 +--- myprog.C +--- TMakefile
The other project library is
/somedir/somewhere/project1/lib1/libproj1lib1.so
.
You want to link it with myprog.C.
There are several ways. One is using link::LIBPATH and link::SYSLIBS
with /somedir/allmyproj/myproj/prog2/TMakefile
. (recommended)
#------------------------------------------------------------ # TMakefile #------------------------------------------------------------ # # where is the other project top dir : full path # set OTHERPROJECTDIR /somedir/somewhere/project1 # # add include directory for compile # lappend cxx::FLAGS -I${OTHERPROJECTDIR}/include # # add the link path. # lappend link::LIBPATH ${OTHERPROJECTDIR}/lib1 # # add the linking library. # lappend link::SYSLIBS projlib1
Or, tell library to ld directory.
#------------------------------------------------------------ # TMakefile #------------------------------------------------------------ # # where is the other project top dir : full path # set OTHERPROJECTDIR /somedir/somewhere/project1 # # add include directory for compile # lappend cxx::FLAGS -I${OTHERPROJECTDIR}/include # # which library do you want to link, exactly # set LIBDIR ${OTHERPROJECTDIR}/lib1 # # according to the gcc document, this must be right, but not works... # # lappend link::FLAGS -Xlinker -rpath -Xlinker ${LIBDIR} -lproj1lib1 # # set the library directory with full pathname. # lappend link::FLAGS ${LIBDIR}/libprojlib1.so
You have a directory which is not under the main project, but you want to link to main project's library.
This is not so good situation, since main projet should be one. However, there is a main project and just you want to test some library. Then, you can put PROJROOT as follows.
#------------------------------------------------------------ # TMakefile #------------------------------------------------------------ set PROJROOT /your/main/projectroot
You can make a static linked object with setting next option of link module. However, you should recompile all. You can check the all libraries are statically linked by command ldd (on Linux). Usually, system libraries are not linked statically. If you want to link all system libraries statically, you should specified system static libraries.
set link::MAKE_SHLIB 0 set link::MAKE_LIB 1 set link::LINK_MODE "static"
It seems ld prefers link to shared library if it exists. So, you need to remove all .so files you created. Then for the whole project, you can use TMakefile.priv for this purpose.
You can check your executable is statically linkd or not with the
command ldd your_exe_file
.
I encountered a strange problem. We linked all library twice since we do not know the order. But, once I had an experience which is not enough for in some case. But I did not understand. I just change the PROJLIB's order (the basic one is later at the TMakefile to make sure), then it works, like next example.
# QtWidgets depends on util # But this once failed in static link library. lappend link::PROJLIBS base/util lappend link::PROJLIBS base/QtWidgets
# This is safer. But tmk has already assumed this situation. # But this works in a case of static linking. lappend link::PROJLIBS base/QtWidgets lappend link::PROJLIBS base/util
gcc 4.5.x passes --as-needed
linker option by default, this
gives you some missing symbol when your program linked shared library
that implicitly linked shared library. For instance,my program links
foo.so and foo.so links libutil.so when I created foo.so, then I got the
following undefined reference errors.
libutil.so: undefined reference to `dlopen' libutil.so: undefined reference to `dlclose' libutil.so: undefined reference to `dlerror' libutil.so: undefined reference to `dlsym'Solving this problem, add
--no-as-needed
linker flag. For
tmk,
append link::FLAGS "-Wl,--no-as-needed"in TMakefile.proj, for instance.
For a package creation, this default setting removes dependency, therefore, this default makes sense. However, this is a difficult problem.
See http://wiki.debian.org/ToolChain/DSOLinking
#------------------------------------------------------------ # how to get/set the environment variable #------------------------------------------------------------ set environment_var_of_HOME $env(HOME) #------------------------------------------------------------ # when you have not $HOME, maybe you can not write #------------------------------------------------------------ set $env(HOME) "/my/home/" #------------------------------------------------------------ # run a command #------------------------------------------------------------ # run a command 1 # set datestr "[ exec date ]" # # run a command 2 ... when you've got a command as a list # set cmd "{date}" set datestr "[ eval exec ${cmd} ]" #------------------------------------------------------------ # How to get the OS type, platform information # ... This is in a tclvars. There is many information you can get. # See tclvars. #------------------------------------------------------------ # array variable tcl_platform gives you platform, os, osVersion, user, etc.. # puts $tcl_platform(platform) # windows, unix, macintosh, ... puts $tcl_platform(os) # Linux, IRIX, SunOS, ... puts $tcl_platform(osVersion) # e.g., 2.4.26.1.p4 on my Linux
Q1: I want to change compile command to tmk
from make -k
.
A1: Add next code to your .emacs
file.
(setq compile-command "tmk ")
However, the effect of above code is global. Then,
Q2: I want to set compile command to tmk
, if and only
if I am in c-mode (c++-mode) and there is a TMakefile
in
the current directory.
A2: In the case of C or C++, you can set
c-mode-common-hook
for customizing your mode.
Next code is effective when
TMakefile
is in the current directory.
Most of emacs mode always provides a hook function like this. So, you may be able to customize your mode in this way.
(defun my-cpp-mode-common-hook () (progn ;; you can write other customizations for your C(C++) mode (if (file-exists-p "TMakefile") (set (make-local-variable 'compile-command) "tmk ")))) (add-hook 'c-mode-common-hook 'my-cpp-mode-common-hook)
Q: When I read a tmk module (*.tmk file) or a TMakefile (TMakefile*), I want to change my emacs major mode to the tcl-mode. How to do it?
A: Add next code to your .emacs
.
(setq auto-mode-alist (append (list '("\\.tmk$" . tcl-mode) '("TMakefile.*$" . tcl-mode)) auto-mode-alist))
Q: I tmked on the top of my project. In that case, emacs can not jump to an error line. Can you help me?
A: Current tmk prints `in directory' and `back in directory' when it changes the directory instead of `Entering directory' and `Leaving directory' of GNU make. Then, you should teach this to emacs. Add next code to your .emacs file.
(progn (defun my-compilation-mode-hook () (setq compilation-enter-directory-regexp "[^\n]*: in directory \\([^\n]*\\)$") (setq compilation-leave-directory-regexp "[^\n]*: back in directory \\([^\n]*\\)$") ) (add-hook 'compilation-mode-hook 'my-compilation-mode-hook))
Q: tmk's $ARCH directory bothers me when I use cvs.
A: You can use .cvsignore
file. A
.cvsignore
file tells to cvs which file should be ignored.
If you want to ignore the Debian3.0/ directory, the
.cvsignore
file may be:
% cat .cvsignore Debian*There are mainly two possible locations to put this file.
.cvsignore
file at your project directory..cvsignore
file.
.cvsignore
file at your home directory.~/.cvsignore
is:
Debian* Redhat* IRIX* SunOS*