Automake and files with the same name
Asked Answered
O

2

5

I've a C++ autoconf managed project that I'm adapting to compile on FreeBSD hosts. The original system was Linux so I made one AM_CONDITIONAL to distinguish the host I'm building and separate the code into system specific files.

configure.ac


AC_CANONICAL_HOST
AM_CONDITIONAL([IS_FREEBSD],false)
case $host in
        *free*)    
            AC_DEFINE([IS_FREEBSD],[1],[FreeBSD Host])
            AM_CONDITIONAL([IS_FREEBSD],true)
            BP_ADD_LDFLAG([-L/usr/local/lib])
                ;;
esac

Makefile.am


lib_LTLIBRARIES=mylib.la
mylib_la_SOURCES=a.cpp \
                 b.cpp

if IS_FREEBSD
    mylib_la_SOURCES+=freebsd/c.cpp
else
    mylib_la_SOURCES+=linux/c.cpp
endif

When I run automake it fails with this kind of message:

Makefile.am: object `c.lo' created by `linux/c.cpp' and `freebsd/c.cpp'

Any ideas on how to configure automake to respect this conditional even in the Makefile.in build proccess?

I this works if the files have diferent names, but it's c++ code and I'm trying to keep the filenames the same as the class name.

Thanks in advance!

Oakman answered 27/5, 2009 at 20:48 Comment(2)
There is a typo in your Makefile.am: "IS_FREEBSD" should read "if IS_FREEBSD".Bodycheck
For the record: The above conditional running of AM_CONDITIONAL will "confuse automake", according to the automake documentation. Better conditionally set an environment variable, and then test that conditionally set env variable in a single unconditional AM_CONDITIONAL.Apeldoorn
B
11

You could request for the objects to be built in their respective subdirectories with

AUTOMAKE_OPTIONS = subdir-objects
Bodycheck answered 28/5, 2009 at 7:37 Comment(2)
It is also possible to configure this automake option in AM_INIT_AUTOMAKE([... subdir-objects ...]) in configure.ac.Apeldoorn
Why do automake create object files for the code which is not told to build? Since it is compiling on a condition, it should take only one file at a time even if it is in same name. Am i right?Sparklesparkler
A
7

Another option, besides subdir-objects, is to give each sub-project some custom per-project build flags. When you do this, automake changes its *.o naming rules to prepend the target name onto the module name. For example, this:

mylib_la_CXXFLAGS=$(AM_CXXFLAGS)
mylib_la_SOURCES=a.cpp b.cpp

will result in the output files mylib_la-a.o and mylib_la-b.o, rather than a.o and b.o. Thus you can have two different projects with the same output directory that each have, say, a b.cpp file, and not have their outputs conflict.

Notice that I did this by setting the project-specific CXXFLAGS to the values automake was already going to use, AM_CXXFLAGS. Automake isn't smart enough to detect this trick and use the shorter *.o names. If it happens that you do need per-project build options, you can of course do that instead of this hack.

There's a whole list of automake variables that, when set on a per-executable basis, give this same effect. So for instance, maybe one sub-project needs special link flags already, so you give it something like:

mylib_la_LDFLAGS=-lfoo

This will give you the prefixed *.o files just as the AM_CXXFLAGS trick did, only now you are "legitimately" using this feature, instead of tricking automake into doing it.

By the way, it's bad autoconf style to change how your program builds based solely on the OS it's being built for. Good autoconf style is to check only for specific platform features, not whole platforms, because platforms change. FreeBSD might be a certain way today, but maybe in the next release it will copy a feature from Linux that would erase the need for you to build your program two different ways. Or, maybe the feature you're using today is deprecated, and will be dropped in the next version.

There's forty years of portable Unix programming wisdom in the autotools, grasshopper. The "maybes" I've given above have happened in the past, and will certainly do so again. Testing individual features is the nimblest way to cope with constantly changing platforms.

You can get unexpected bonuses from this approach, too. For instance, maybe your program needs two nonportable features to do its work. Say that on FreeBSD, these are the A and B features, and on Linux, they're the X and Y features; A and X are similar mechanisms but with different interfaces, and the same for B and Y. It could be that feature A comes from the original BSDs, and is in Solaris because it has BSD roots from SunOS in the 80's, and Solaris also has feature Y from it's System V based redesign in the early 90's. By testing for these features, your program could run on Solaris, too, because it has the features your program needs, just not in the same combination as on FreeBSD and Linux.

Abdication answered 10/8, 2009 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.