Jam - Using a single target in multiple directories
Sometimes, desire to use an object file in multiple directories arises. Assume the following directory structure.
- src/common/tests
- src/unittest
A test in common/tests need only one object in unittest to be linked, but one does not want to make it as a library for that.
Simple method
Most simple method is to just use it. In Jamfile of common/tests, refer to the file in unittest directory as below.
This brings a small problem.
Because unittest.c of Jamfile in unittest directory and
../../unittest/unittest.c above are different targets,
unittest.c compiles twice for an update.
Sometimes this is a feature rather than a problem,
like when different CFLAGS (e.g., -DIN_TEST) is needed for a testing purpose.
But even in that situation, there’s a problem.
Because those two targets are bound to the same file,
if unittest.o is already built in unittest directory,
an object without intented CFLAGS applied could be used for testing instead.
In this case, do as below.
SEARCH on [ FGristFiles unittest.c ] = $(SUBDIR)/../../unittest ;
CFLAGS on [ FGristFiles unittest.o ] += -DIN_TEST ;
Personally, I prefer not to use different compiler flags for real and test object because that could give a different result.
Solution
Define a rule in Jamrules, as below.
local _path = [ FRelPath $(SUBDIR_TOKENS) : $(top_tokens[2-]) ] ;
local _file ;
for _file in $(files) {
local _gristed = [ FGristFiles $(_file:R=$(_path)) ] ;
local _remote_grist = [ FGrist $(top_tokens[2-]) ] ;
Depends $(_gristed) : $(_file:BSG=$(_remote_grist:E)) ;
LOCATE on $(_gristed) = $(SUBDIR) ;
SEARCH on $(_gristed) = $(SUBDIR) ;
}
return [ FGristFiles $(files:R=$(_path)) ] ;
}
And use in Jamfile as below.
Objects common_tests.c ;
[ RemoteFiles unittest.o : TOP unittest ] returns ../../unittest/unittest.o with common grist
which depends on unittest.o with unittest grist.
Advantage of this method is that the rule and variable settings of the Jamfile
in the directory which the object resides in is consistently used everywhere.
Make it a library
In most cases, this is the correct approach.
Make it a library with Library and link with LinkLibraries.
- moonz's blog
- Login to post comments
- 한국어