I'm developing a project that is currently written in C but I plan to write some of the functions in ASM for at least two platforms (x86_64 and arm). So I might have some source files:
I'd like it so that the configure script chooses the .s files over the .c files when possible. So building on arm will be one.s, two.c, three.c etc.
It seems difficult or impossible to do this nicely with Automake. But if I ditch Automake I'll have to track my own dependencies (ugh).
What's the best way to do this?
The configure.ac file is used to create the ./configure script. It consists of a series of macros which are processed and expanded by autoconf . These macros can check for packages and libraries, handle --enable and --with switches, and generate various files.
The Autotools are a group of programs that create a GNU Build System for a given software package. It is a suite of tools that work together to produce various build resources, such as a Makefile (to be used with GNU Make). Thus, Autotools can be considered a de facto build system generator.
Here's what I do.
configure.ac
...
AC_CANONICAL_SYSTEM
AM_PROG_AS
AC_PROG_CC
...
PROC=""
AS_CASE([$host_cpu], [x86_64], [PROC="x86_64"], [arm*], [PROC="arm"])
AM_CONDITIONAL([CPU_X86_64], [test "$PROC" = "x86_64"])
AM_CONDITIONAL([CPU_ARM], [test "$PROC" = "arm"])
AM_CONDITIONAL([CPU_UNDEFINED], [test "x$PROC" = "x"])
Makefile.am
lib_LTLIBRARIES = libfoo.la
libfoo_la_SOURCES = \
$(top_srcdir)/generic/three.c
if CPU_ARM
libfoo_la_SOURCES += $(top_srcdir)/arm/one.s \
$(top_srcdir)/generic/two.c
endif
if CPU_X86_64
libfoo_la_SOURCES += $(top_srcdir)/generic/one.c \
$(top_srcdir)/x86_64/two.s
endif
if CPU_UNDEFINED
libfoo_la_SOURCES += $(top_srcdir)/generic/one.c \
$(top_srcdir)/generic/two.c
endif
The Conditional Sources section of the automake manual should point you in the right direction. You're going to want AC_CANONICAL_HOST
in configure.ac
and then make decisions based on the value of $host
.
automake
won't like it if two files can compile to the same object. If you can't rename the sources like in the linked part of the manual, you may want to try something like this (make sure you have subdir-objects
in AM_INIT_AUTOMAKE
:
# Note the $() isn't a shell command substitution.
# The quoting means it'll be expanded by `make'.
MODULE_ONE_OBJ='generic/one.$(OBJEXT)'
MODULE_TWO_OBJ='generic/two.$(OBJEXT)'
case $host in
# ...
arm*)
MODULE_ONE='arm/one.$(OBJEXT)'
;;
x86_64)
MODULE_TWO='x86/two.$(OBJEXT)'
;;
esac
AC_SUBST([MODULE_ONE])
AC_SUBST([MODULE_TWO])
In Makefile.am
:
bin_PROGRAMS = foo
foo_SOURCES = foo.c
EXTRA_foo_SOURCES = arm/one.s x86/two.c
foo_LDADD = $(MODULE_ONE) $(MODULE_TWO)
foo_DEPENDENCIES = $(MODULE_ONE) $(MODULE_TWO)
You can use AC_CANONICAL_HOST and then conditionally select the correct subdirectory. For example, in configure.ac
:
AC_CANONICAL_HOST
AC_SUBST([USE_DIR],[$host_cpu])
test -d $srcdir/$USE_DIR || USE_DIR=generic
and then in Makefile.am
:
SUBDIRS = $(USE_DIR) common
and in common/Makefile.am
:
LDADD = ../$(USE_DIR)/libfoo.a
and in each ${host_cpu}/Makefile.am
:
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = one.s ../common/two.c
This uses a slightly different directory structure than you describe. C files that are used on all platforms would go in common
and be linked to a convenience library constructed in the platform specific directory. If some c files are used on only some platforms, you could put them in common and reference them explicitly in the Makefile.am for the platforms that need them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With