Discussion:
_SHORTNAME in conditional
Thomas Martitz
2016-01-05 21:05:59 UTC
Permalink
Hello,

Given this fragment:

bin_PROGRAMS = false true
true_SOURCES = false.c
true_CFLAGS = -DAM_TRUE
true_SHORTNAME = t
if FOO
false_SOURCES = false.c
false_CFLAGS = -DAM_FALSE
false_SHORTNAME = f
endif

I receive a warning for false_SHORTNAME:
Makefile.am:9: warning: automake does not support false_SHORTNAME being
defined conditionally

What does that mean? Why is it unsupported? Other variables work just fine.

This is a problem for me, because I'm trying to construct the following:

root/Makefile.am:
if ENABLE_FOO
include foo/Makefile.inc
endif

root/foo/Makefile.inc
bin_PROGRAMS = foo
foo_SOURCES = foo.c
foo_SHORTNAME = foo

As of now, there is no way to achieve that as the warning also appears
for foo_SHORTNAME. The workaround to move the conditional into
root/foo/Makefile.inc is ugly and breaks modularization of the project.

Automake source code is a myth to me, I wasn't able to find the code
that implements this limitation (only the place where the warning is
printed (variable_value() => $self->check_defined_unconditionally in
Variable.pm)

Best regards.
Thomas Martitz
2016-01-06 06:01:57 UTC
Permalink
Automake source code is a myth to me, I wasn't able to find the code that
implements this limitation (only the place where the warning is printed
(variable_value() => $self->check_defined_unconditionally in Variable.pm)
There's the following code in the top-level 'automake' script -
if ($var)
{
# FIXME: should use the same Condition as
# the _SOURCES variable. But this is really
# silly overkill -- nobody should have
# conditional shortnames.
$dname = $var->variable_value;
}
does that help?
I saw that, but I couldn't make sense of it. What does that mean? I get
that the developer deemed it overkill but I can't follow that reason.

Best regards
Gavin Smith
2016-01-06 12:15:34 UTC
Permalink
Post by Thomas Martitz
Automake source code is a myth to me, I wasn't able to find the code that
implements this limitation (only the place where the warning is printed
(variable_value() => $self->check_defined_unconditionally in Variable.pm)
There's the following code in the top-level 'automake' script -
if ($var)
{
# FIXME: should use the same Condition as
# the _SOURCES variable. But this is really
# silly overkill -- nobody should have
# conditional shortnames.
$dname = $var->variable_value;
}
does that help?
I saw that, but I couldn't make sense of it. What does that mean? I get
that the developer deemed it overkill but I can't follow that reason.
Whoever wrote that, if they are still around, can speak for
themselves, but I'll try to explain what I remember from my foray into
the Automake source code a couple of years ago.

The Automake conditional construct means that variables don't have to
have a single value:

if COND
VAR=val1
else
VAR=val2
endif

Here VAR has two values.

Each Automake conditional tests only a single condition. They can also
be nested:

if COND1
if COND2
VAR=val
endif
endif

Adding more conditions reduces the number of occasions that the
contained definition is applicable. The definition here is valid if
"COND1" AND "COND2".

A sequence of nested conditionals can be represented by a list of
conditionals: COND1 AND !COND2 AND COND3.

What about no conditionals at all? This is represented by TRUE. TRUE
is appropriate because when you add more conditions to it, it
disappears: TRUE AND CONDITION is equivalent to CONDITION.

This should answer the question of why when you ask for a definition
under the TRUE condition of a conditionally defined variable, it gives
an error: a definition for the TRUE condition would be an
unconditional definition. (I found this point confusing, myself.)

Note also that the word "Condition" as used in the Automake source
code has a narrower meaning than its common sense: it refers to a
conjunction of conditions only (AND), and not OR for the union of two
conditions.

When asking for a variables value, you have to specify the condition.
From Variable.pm:

Therefore obtaining the value of a variable under a given
condition involves two lookups. One to look up the variable,
and one to look up the conditional definition:

my $var = var $name;
if ($var)
{
my $def = $var->def ($cond);
if ($def)
{
return $def->value;
}
...
}
...

What remains, I believe, is how to get the right condition to look up
the value of the *_SHORTNAME value. I assume that mustn't be easy,
otherwise they would have done it.

(In my humble opinion, Automake conditionals muddle the Automake
source code terribly. DisjConjunctions.pm and Conjunctions.pm together
constitute a weird reimplementation of the Boolean algebra that is
present in every programming language. I thought when I was looking at
the code before that it would at least twice as easy to understand the
code if this feature wasn't present.)
Thomas Martitz
2016-01-06 12:29:50 UTC
Permalink
Hi,

I've written an RFC patch that solves my root problem so that I wouldn't
have to use _SHORTNAME at all. Please have a look at that and comment on it!

I'll still follow-up with my findings regarding _SHORTNAME below.
Post by Gavin Smith
Post by Thomas Martitz
Automake source code is a myth to me, I wasn't able to find the code that
implements this limitation (only the place where the warning is printed
(variable_value() => $self->check_defined_unconditionally in Variable.pm)
There's the following code in the top-level 'automake' script -
if ($var)
{
# FIXME: should use the same Condition as
# the _SOURCES variable. But this is really
# silly overkill -- nobody should have
# conditional shortnames.
$dname = $var->variable_value;
}
does that help?
I saw that, but I couldn't make sense of it. What does that mean? I get
that the developer deemed it overkill but I can't follow that reason.
Whoever wrote that, if they are still around, can speak for
themselves, but I'll try to explain what I remember from my foray into
the Automake source code a couple of years ago.
The Automake conditional construct means that variables don't have to
if COND
VAR=val1
else
VAR=val2
endif
Here VAR has two values.
Each Automake conditional tests only a single condition. They can also
if COND1
if COND2
VAR=val
endif
endif
Adding more conditions reduces the number of occasions that the
contained definition is applicable. The definition here is valid if
"COND1" AND "COND2".
A sequence of nested conditionals can be represented by a list of
conditionals: COND1 AND !COND2 AND COND3.
What about no conditionals at all? This is represented by TRUE. TRUE
is appropriate because when you add more conditions to it, it
disappears: TRUE AND CONDITION is equivalent to CONDITION.
This should answer the question of why when you ask for a definition
under the TRUE condition of a conditionally defined variable, it gives
an error: a definition for the TRUE condition would be an
unconditional definition. (I found this point confusing, myself.)
Note also that the word "Condition" as used in the Automake source
code has a narrower meaning than its common sense: it refers to a
conjunction of conditions only (AND), and not OR for the union of two
conditions.
When asking for a variables value, you have to specify the condition.
Therefore obtaining the value of a variable under a given
condition involves two lookups. One to look up the variable,
my $var = var $name;
if ($var)
{
my $def = $var->def ($cond);
if ($def)
{
return $def->value;
}
...
}
...
What remains, I believe, is how to get the right condition to look up
the value of the *_SHORTNAME value. I assume that mustn't be easy,
otherwise they would have done it.
(In my humble opinion, Automake conditionals muddle the Automake
source code terribly. DisjConjunctions.pm and Conjunctions.pm together
constitute a weird reimplementation of the Boolean algebra that is
present in every programming language. I thought when I was looking at
the code before that it would at least twice as easy to understand the
code if this feature wasn't present.)
Thanks for you insight. In the meantime, I think I found why _SHORTNAME
in particular is unsupported (however I still haven't found the code
that implements this particular decision).

Anyway, I believe the reason is that automake already fully resolves the
object names (and consequently _SHORTNAME) at Automake-time.
I.e. Makefile.in contains:
foo_OBJECTS = bar_foo-foo.o
Other variables are substituted at configure time (using @VAR_TRUE@).

That's it. Automake conditionals are ultimately resolved at configure
time, but that's too late for the implementation of _SHORTNAME.

Now, you could do something like in Makefile.in
@VAR_TRUE@$(am_foo_SHORTNAME) = bar_foo
@VAR_FALSE@$(am_foo_SHORTNAME) =
foo_OBJECTS = $(am_foo_SHORTNAME)foo.o

and resolve that at configure time, but that's simply not implemented
currently. I guess that's why there is a TODO in the automake script
(see at the beginning of this mail).

Best regards
Thomas Martitz
2016-01-06 07:31:00 UTC
Permalink
Post by Thomas Martitz
Hello,
bin_PROGRAMS = false true
true_SOURCES = false.c
true_CFLAGS = -DAM_TRUE
true_SHORTNAME = t
if FOO
false_SOURCES = false.c
false_CFLAGS = -DAM_FALSE
false_SHORTNAME = f
endif
Makefile.am:9: warning: automake does not support false_SHORTNAME
being defined conditionally
What does that mean? Why is it unsupported? Other variables work just fine.
if ENABLE_FOO
include foo/Makefile.inc
endif
root/foo/Makefile.inc
bin_PROGRAMS = foo
foo_SOURCES = foo.c
foo_SHORTNAME = foo
As of now, there is no way to achieve that as the warning also appears
for foo_SHORTNAME. The workaround to move the conditional into
root/foo/Makefile.inc is ugly and breaks modularization of the project.
Automake source code is a myth to me, I wasn't able to find the code
that implements this limitation (only the place where the warning is
printed (variable_value() => $self->check_defined_unconditionally in
Variable.pm)
To give some more context: the root issue I'm trying to resolve is that
object filenames are constructed from the paths leading to it, even for
subdir-objects.

I.e.
in a sub-Makefile.am
bin_PROGRAMS += %D%/foo
%C%_foo_SOURCES = foo.c

The object file will be called path_to_foo-foo.o. I do not want this, I
want the file to be just called foo-foo.o. I ensure via subdir-objects
that everything is unique.

Why do I want to avoid the standard object filename? I also construct a
Makefile in the foo subdirectory. This is so that I can run make in the
root directory and also in root/foo. In both make invocations, the same
object file shall be created. This only works if the object filename
does not include the path that leads to the object file.

This scheme works fine with %C%_foo_SHORTNAME unless I want to
conditionally build the foo subdirectory in which case the warning.

I guess this means there is another viable solution to my root problem.
Instead of having to use _SHORTNAME I could envision an automake option
that surpresses the object filename construction like above and only
uses the foo part of %C%_foo_SOURCES.

PS: Please don't suggest recursive automake, this is what I'm actually
trying to get away from.

Best regards.
Thomas Martitz
2016-01-06 09:17:52 UTC
Permalink
This option is intended to be used in conjunction with subdir-objects and
Automake-time substitutions for included makefile fragments (%C%, %D%). It
suppresses the generation path components in object filenames.

It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.

Example:
without object-shortname
root/path/to/Makefile.am:
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)

results in objects:
root/path/to/root_path_to_foo-foo.o

with object-shortname the object filename is:
root/path/to/foo-foo.o

And it allows the following in root/Makefile.am (not possible with foo_SHORTNAME=foo)
if ENABLE_FOO
include path/too/Makefile.am
endif
---
bin/automake.in | 6 ++++++
lib/Automake/Options.pm | 1 +
2 files changed, 7 insertions(+)

diff --git a/bin/automake.in b/bin/automake.in
index eedc8bc..1b40992 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -1691,6 +1691,12 @@ sub handle_single_transform
# override.

my $dname = $derived;
+ if (option 'object-shortname') {
+ # If object-shortname is enabled the object's filename shall not contain the parts
+ # derived from its path (e.g. if %C% is used), but just the name of the object's target
+ # e.g. instead of path_to_binary-object.o just binary-object
+ $dname = split ('_', $derived)[-1];
+ }
my $var = var ($derived . '_SHORTNAME');
if ($var)
{
diff --git a/lib/Automake/Options.pm b/lib/Automake/Options.pm
index 7d782c3..819c5ff 100644
--- a/lib/Automake/Options.pm
+++ b/lib/Automake/Options.pm
@@ -293,6 +293,7 @@ sub _is_valid_easy_option ($)
silent-rules
std-options
subdir-objects
+ object-shortname
);
}
--
2.6.4
Thomas Martitz
2016-01-06 09:23:47 UTC
Permalink
This option is intended to be used in conjunction with subdir-objects and
Automake-time substitutions for included makefile fragments (%C%, %D%). It
suppresses the generation path components in object filenames.

It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.

Example:
without object-shortname
root/path/to/Makefile.am:
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)

results in objects:
root/path/to/root_path_to_foo-foo.o

with object-shortname the object filename is:
root/path/to/foo-foo.o

And it allows the following in root/Makefile.am (not possible with foo_SHORTNAME=foo)
if ENABLE_FOO
include path/too/Makefile.am
endif
---
bin/automake.in | 6 ++++++
lib/Automake/Options.pm | 1 +
2 files changed, 7 insertions(+)

diff --git a/bin/automake.in b/bin/automake.in
index eedc8bc..0d104cb 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -1691,6 +1691,12 @@ sub handle_single_transform
# override.

my $dname = $derived;
+ if (option 'object-shortname') {
+ # If object-shortname is enabled the object's filename shall not contain the parts
+ # derived from its path (e.g. if %C% is used), but just the name of the object's target
+ # e.g. instead of path_to_binary-object.o just binary-object
+ $dname = (split ('_', $derived))[-1];
+ }
my $var = var ($derived . '_SHORTNAME');
if ($var)
{
diff --git a/lib/Automake/Options.pm b/lib/Automake/Options.pm
index 7d782c3..819c5ff 100644
--- a/lib/Automake/Options.pm
+++ b/lib/Automake/Options.pm
@@ -293,6 +293,7 @@ sub _is_valid_easy_option ($)
silent-rules
std-options
subdir-objects
+ object-shortname
);
}
--
2.6.4
Gavin Smith
2016-01-08 14:33:11 UTC
Permalink
Post by Thomas Martitz
This option is intended to be used in conjunction with subdir-objects and
Automake-time substitutions for included makefile fragments (%C%, %D%). It
suppresses the generation path components in object filenames.
It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.
without object-shortname
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)
root/path/to/root_path_to_foo-foo.o
root/path/to/foo-foo.o
And it allows the following in root/Makefile.am (not possible with foo_SHORTNAME=foo)
if ENABLE_FOO
include path/too/Makefile.am
endif
The conditional could be moved into the Makefile fragment and the
SHORTNAME left outside of it. I don't know if that's desirable for
you.

Failing that, it would be better for conditional SHORTNAME to work,
instead of adding a new option.
Gavin Smith
2016-01-08 15:03:23 UTC
Permalink
Post by Gavin Smith
Failing that, it would be better for conditional SHORTNAME to work,
instead of adding a new option.
For example:

--- automake-orig 2016-01-08 14:54:04.000000000 +0000
+++ /home/g/local/bin/automake 2016-01-08 15:06:06.000000000 +0000
@@ -1749,11 +1749,18 @@
my $var = var ($derived . '_SHORTNAME');
if ($var)
{
- # FIXME: should use the same Condition as
- # the _SOURCES variable. But this is really
- # silly overkill -- nobody should have
- # conditional shortnames.
- $dname = $var->variable_value;
+ # Use the same Condition as the _SOURCES variable.
+ my $sources_var = var ($derived . '_SOURCES');
+ if ($sources_var) {
+ my @conds = $sources_var->conditions->conds;
+ if (@conds) {
+ my $cond = $conds[0];
+ my $def = $var->def($cond);
+ if ($def) {
+ $dname = $def->value;
+ }
+ }
+ }
}
$object = $dname . '-' . $object;
Thomas Martitz
2016-01-08 15:47:03 UTC
Permalink
Post by Gavin Smith
Post by Gavin Smith
Failing that, it would be better for conditional SHORTNAME to work,
instead of adding a new option.
--- automake-orig 2016-01-08 14:54:04.000000000 +0000
+++ /home/g/local/bin/automake 2016-01-08 15:06:06.000000000 +0000
@@ -1749,11 +1749,18 @@
my $var = var ($derived . '_SHORTNAME');
if ($var)
{
- # FIXME: should use the same Condition as
- # the _SOURCES variable. But this is really
- # silly overkill -- nobody should have
- # conditional shortnames.
- $dname = $var->variable_value;
+ # Use the same Condition as the _SOURCES variable.
+ my $sources_var = var ($derived . '_SOURCES');
+ if ($sources_var) {
+ my $cond = $conds[0];
+ my $def = $var->def($cond);
+ if ($def) {
+ $dname = $def->value;
+ }
+ }
+ }
}
$object = $dname . '-' . $object;
What does Makefile.in look like with that? I found that _SHORTNAME is
evaluated at automake-time which is probably the reason it's not
supported in a conditional. I didn't think it would be feasible to make
_SHORTNAME work (not for me anyway, I'm completely new to automake's
source code).

I'd still prefer the option because it has the bonus of avoiding
repetitions like the following all over the place:

bin_PROGRAMS += foo
foo_SHORTNAME = foo

Thank you anyway!
Gavin Smith
2016-01-08 15:55:16 UTC
Permalink
Post by Thomas Martitz
It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.
without object-shortname
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)
root/path/to/root_path_to_foo-foo.o
root/path/to/foo-foo.o
If you can get this to work, I can't think of a reason why it
shouldn't be done all the time, unconditionally, without an option.
Post by Thomas Martitz
+ # If object-shortname is enabled the object's filename shall not contain the parts
+ # derived from its path (e.g. if %C% is used), but just the name of the object's target
+ # e.g. instead of path_to_binary-object.o just binary-object
+ $dname = split ('_', $derived)[-1];
+ }
This isn't completely correct. From the Automake manual:

For example, if a program is named 'sniff-glue', this would be
canonicalized as 'sniff_glue'. An example of a derived variable name is
'sniff_glue_SOURCES' (not 'sniff-glue_SOURCES'.) Similarly, the sources
for a library named 'libmumble++.a' would be listed in the
'libmumble___a_SOURCES' variable.

The code you've given here would set the "short name" as "glue", not
"sniff_glue".
Thomas Martitz
2016-01-08 16:05:48 UTC
Permalink
Post by Gavin Smith
Post by Thomas Martitz
It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.
without object-shortname
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)
root/path/to/root_path_to_foo-foo.o
root/path/to/foo-foo.o
If you can get this to work, I can't think of a reason why it
shouldn't be done all the time, unconditionally, without an option.
I agree, as I have no use for the current naming scheme. I was just
uneasy about changing current behaviour like this, maybe someone depends
on the naming (perhaps for custom rules)?
Post by Gavin Smith
Post by Thomas Martitz
+ # If object-shortname is enabled the object's filename shall not contain the parts
+ # derived from its path (e.g. if %C% is used), but just the name of the object's target
+ # e.g. instead of path_to_binary-object.o just binary-object
+ $dname = split ('_', $derived)[-1];
+ }
For example, if a program is named 'sniff-glue', this would be
canonicalized as 'sniff_glue'. An example of a derived variable name is
'sniff_glue_SOURCES' (not 'sniff-glue_SOURCES'.) Similarly, the sources
for a library named 'libmumble++.a' would be listed in the
'libmumble___a_SOURCES' variable.
The code you've given here would set the "short name" as "glue", not
"sniff_glue".
You are right. Thanks for noticing. I'll see if I can fix that.

Best regards
Thomas Martitz
2016-01-08 19:30:13 UTC
Permalink
This option is intended to be used in conjunction with subdir-objects and
Automake-time substitutions for included makefile fragments (%C%, %D%). It
suppresses the generation path components in object filenames.

It should equivalent to setting %C%_foo_SHORTNAME=foo, except it can work if
the makefile fragment is conditionally included, which improves the modularity
of Automake-using projects.

Example:
without object-shortname
root/path/to/Makefile.am:
bin_PROGRAMS += foo
%C%_foo_CFLAGS = $(CFLAGS)

results in objects:
root/path/to/root_path_to_foo-foo.o

with object-shortname the object filename is:
root/path/to/foo-foo.o

And it allows the following in root/Makefile.am (not possible with foo_SHORTNAME=foo)
if ENABLE_FOO
include path/too/Makefile.am
endif
---
bin/automake.in | 13 +++++++++++++
lib/Automake/Options.pm | 1 +
2 files changed, 14 insertions(+)

diff --git a/bin/automake.in b/bin/automake.in
index eedc8bc..cea04c6 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -1691,6 +1691,19 @@ sub handle_single_transform
# override.

my $dname = $derived;
+ if (option 'object-shortname') {
+ # If object-shortname is enabled the object's filename shall not contain the parts
+ # derived from its path (e.g. if %C% is used), but just the name of the object's target
+ # e.g. instead of path_to_binary-object.o just binary-object
+ my $dirname = dirname ($_file);
+ if ($dirname ne ".") {
+ my $canon_dirname = canonicalize ($dirname) . "_";
+ # paranoid check: should never fail but ensure path prefix is part of the filename
+ if (index ($derived, $canon_dirname) == 0) {
+ $dname = substr ($derived, length ($canon_dirname));
+ }
+ }
+ }
my $var = var ($derived . '_SHORTNAME');
if ($var)
{
diff --git a/lib/Automake/Options.pm b/lib/Automake/Options.pm
index 7d782c3..819c5ff 100644
--- a/lib/Automake/Options.pm
+++ b/lib/Automake/Options.pm
@@ -293,6 +293,7 @@ sub _is_valid_easy_option ($)
silent-rules
std-options
subdir-objects
+ object-shortname
);
}
--
2.7.0
Thomas Martitz
2016-03-04 21:19:54 UTC
Permalink
Hello,

I know there is no currently active maintainer. However, there is an
important bug fix in the current git, and I've postet a patch for review
that I really need for my projects.

Is there any possibility that my patch can be reviewed and merged, and
that one more release can happen, even if just one?

I would love to help but my knowledge about the automake codebase is
poor so I don't feel qualified to step up as maintainer myself. On the
other hand, if nobody is going to do the job, what can I do?

Best regards.

Loading...