using multiple targets

98 views
Skip to first unread message

rahul

unread,
Mar 9, 2010, 4:59:11 AM3/9/10
to tup-users
In our project, we have different flags for building optimized and
debug builds, and have a static build resulting in .a bundle, and a
shared build resulting in .so file from the same source files. At any
point of time we generally build only one target.
i.e
SRC=hello.c square.c
ifdef DEBUG
FLAGS=$(DEBUG_FLAGS)
else
FLAGS=$(OPTIMIZED_FLAGS)
endif

mylib.so: $(SRC)
$(CC) $(FLAGS) -shared $(SRC) -o $@
mylib.a: $(SRC)
$(CC) $(FLAGS) -static $(SRC) -o $@

build_static: mylib.a
build_shared: mylib.so

#make build_static
#make build_shared
#make DEBUG=1 build_static

etc.
Any pointers to convert to Tup file? Also can I select only a part of
the tree to build?
I checked the man page and the examples, but I didn't find a way.

Sam Fredrickson

unread,
Mar 9, 2010, 12:56:39 PM3/9/10
to tup-users
I don't believe that tup has a way to only build one target; instead,
tup ensures that all targets get updated if they need to be. That
means that in your project, each build would have to make both the
static and shared versions of the library.

You'll also want to change your build logic in tup so that each module
compiles separately, instead of compiling the library from all the
source files and linking them together in one go. Since shared and
static objects are different, each module will need to be compiled
twice; for example, module "foo" would become "foo_shared.o" and
"foo_static.o". Then you can link all the static objects together to
form the static library, and the shared objects for the shared
library.

Tup does support configuration options specified in the file
"tup.config" of the project's root directory. Example contents of this
file:

CONFIG_PROJECTNAME_DEBUG=y

Of course replacing "PROJECTNAME" with the name of your project. Then
in a Tupfile (or, more likely, in Tuprules.tup), you can use logic
like this:

CFLAGS = whatever flags are common to both build types
ifeq(@(PROJECTNAME_DEBUG),y)
CFLAGS += whatever flags are specific to the debug build
else
CFLAGS += whatever flags are specific to the regular build
endif

Rahul

unread,
Mar 9, 2010, 1:37:35 PM3/9/10
to tup-...@googlegroups.com
> I don't believe that tup has a way to only build one target; instead,
> tup ensures that all targets get updated if they need to be. That
> means that in your project, each build would have to make both the
> static and shared versions of the library.

It is going to be quite painful to do this :( (being forced to build a target
we dont need - for e.g we have tinderboxes for static and shared builds
separately, and the turn around time will just double). Is there a chance
of this being considered at a future time?

> You'll also want to change your build logic in tup so that each module
> compiles separately, instead of compiling the library from all the
> source files and linking them together in one go. Since shared and
> static objects are different, each module will need to be compiled
> twice; for example, module "foo" would become "foo_shared.o" and
> "foo_static.o". Then you can link all the static objects together to
> form the static library, and the shared objects for the shared
> library.

this is ok I suppose

Thanks,
Rahul

Sam Fredrickson

unread,
Mar 9, 2010, 2:50:08 PM3/9/10
to tup-users
On Mar 9, 10:37 am, Rahul <rahul.g.n...@gmail.com> wrote:
> It is going to be quite painful to do this :( (being forced to build a target
> we dont need - for e.g we have tinderboxes for static and shared builds
> separately, and the turn around time will just double). Is there a chance
> of this being considered at a future time?

It shouldn't be painful at all. If your current Makefile resembles the
one you posted, then builds are taking much longer than they need to,
even by make's standards. Compiling each module individually will
allow tup to be able to just compile those modules which have changed,
and then relink the new object files with the existing previously
compiled object files to form a new library. Even though each time you
change a module you'll need to build it twice, once for static and
once for shared, there should still be a build time improvement
compared to what you're doing now, since you're only compiling one
module instead of all of them.

Mike Shal

unread,
Mar 9, 2010, 9:10:09 PM3/9/10
to tup-...@googlegroups.com
On 3/9/10, Sam Fredrickson <king...@gmail.com> wrote:
> I don't believe that tup has a way to only build one target; instead,
> tup ensures that all targets get updated if they need to be. That
> means that in your project, each build would have to make both the
> static and shared versions of the library.

Correct - tup doesn't have the ability to stop part-way through the build.

>
> You'll also want to change your build logic in tup so that each module
> compiles separately, instead of compiling the library from all the
> source files and linking them together in one go. Since shared and
> static objects are different, each module will need to be compiled
> twice; for example, module "foo" would become "foo_shared.o" and
> "foo_static.o". Then you can link all the static objects together to
> form the static library, and the shared objects for the shared
> library.
>
> Tup does support configuration options specified in the file
> "tup.config" of the project's root directory. Example contents of this
> file:
>
> CONFIG_PROJECTNAME_DEBUG=y
>
> Of course replacing "PROJECTNAME" with the name of your project. Then
> in a Tupfile (or, more likely, in Tuprules.tup), you can use logic
> like this:
>
> CFLAGS = whatever flags are common to both build types
> ifeq(@(PROJECTNAME_DEBUG),y)
> CFLAGS += whatever flags are specific to the debug build
> else
> CFLAGS += whatever flags are specific to the regular build
> endif

This is good advice. You can also extend the use of the config options
to choose whether to build the shared library, static library, or
both. Something like:

ifeq (@(PROJECTNAME_STATIC),y)
: foreach *.c |> gcc -c %f -o %o $(CFLAGS) |> %B_static.o {static_objs}
: {static_objs} |> ar cr %o %f |> mylib.a
endif

ifeq (@(PROJECTNAME_SHARED),y)
: foreach *.c |> gcc -fpic -c %f -o %o $(CFLAGS) |> %B_shared.o {shared_objs}
: {shared_objs} |> gcc -fpic -shared %f -o %o |> mylib.so
endif

Then your tup.config may look like:
CONFIG_PROJECTNAME_STATIC=y
CONFIG_PROJECTNAME_SHARED=y
CONFIG_PROJECTNAME_DEBUG=y

This would generate both versions of the library with debug flags. If
you want to be really snazzy you can describe these build options in a
Kconfig file and use kconfig to generate tup.config rather than
editing it by hand.

-Mike

Reply all
Reply to author
Forward
0 new messages