Hi Matt,
On Wed, Jan 16, 2013 at 3:34 PM, Matt Oswald <
mos...@gmail.com> wrote:
> I find it counter intuitive that a Tupfile lives with the output, rather
> than the source. If I'm mimicking a more Windows-centric (Visual Studio)
> build, I've got to create my Tupfile in an intermediate folder and another
> in an output folder. I'd find it a lot easier to have one Tupfile in the
> source folder that builds the source into another folder, then links that
> source into a final executable in yet another folder.
>
> Will this scenario ever be directly supported?
Personally I find it easier to figure out what's going on with the
Tupfile in the same directory - want to know how files are created
here? Just open the Tupfile!
But, I understand that there are cases where outputting files to
different directories can be useful (re: the threads on supporting
install, probably putting a Tupfile in /usr/bin won't be a good
solution). It's not impossible to do so, but the primary difficulty
lies in how tup parses directories, when it creates nodes in the
database, and how wildcards are handled. I think a different (possibly
backwards incompatible) approach would be needed, but I don't know for
sure.
For example, consider this setup:
lib/Tupfile:
: |> ... |> foo.o
: |> ... |> bar.o
: *.o |> link |> lib.a
: |> ... |> not_included.o
other/Tupfile:
: |> ... |> ../lib/other.o
Tup may parse lib/Tupfile first, and so when it goes to resolve the
*.o in the link line, it will be looking at a combination of the
file-system (which probably just has foo.c and bar.c), as well as the
outputs of rules in previous lines (foo.o and bar.o). Note that
not_included.o is not included in the library, since it is listed
after the link line. This is true even if not_included.o has already
been compiled and is in the file-system.
Now, if you have other/Tupfile that is also generating a .o file in
lib/, where should it be generated? One option is to put them all at
the 'end', so other.o is like not_included.o and doesn't get linked
in. But, that makes it difficult to actually put things together
(which is presumably what you'd want to do). Another option is to put
them all first, so *.o resolves all objects coming from other
Tupfiles. This could work if the *.o resolution was moved out of the
parser and put into the updater when the command is dispatched.
However, I don't know of a way to easily exclude not_included.o if
this approach is taken.
If instead we change the meaning of *.o to mean 'any object in the
directory' rather than 'any object created until this point in the
Tupfile', then this example would link foo.o, bar.o, not_included.o,
and ../lib/other.o, which is probably the most sensible in this case.
However, this breaks the shell-script like top-down readability of
Tupfiles. It would also break things like:
: foreach *.c |> gcc ... |> %B.o
: *.o |> link ... |> file_generator
: file_generator |> ./file_generator > %o |> generated_file.c
Since this would then create a circular dependency (generated_file.c
-> generated_file.o -> file_generator -> generated_file.c)
What do you think?
-Mike