0
votes

I am looking to use automake for a project with a lot of subdirectories. What I want to achieve is compiling all of the source code in all of the subdirectories into one executable on linux.

Right now I am using subdir-objects where I have to manually specify the paths of each of the source code files for the entire heirarchy.

I had tried using LTLIBRARIES approach using Makefile.am for each of the subdirectories, but for some reason the program does not compile and gives me a lot of undefined reference errors.

And right now my Makefile.am file looks like this:

AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = a.out
a_out_SOURCES = EntryPoint.cpp ./glad/src/glad.cpp ./ImageLoader/ImageLoader.cpp ./FileIO/FileIO.cpp ./Debug/DebugLog.cpp ./Object/Object.cpp \
./Texture/Texture.cpp ./Window/Window.cpp ./Shader/Shader.cpp
include_HEADERS = ./glad/include/glad/glad.h ./ImageLoader/stb_image.h ./FileIO/FileIO.h ./Debug/DebugLog.h ./Object/Object.h \
./Texture/Texture.h ./Window/Window.h ./Shader/Shader.h
a_out_LDADD = -lGLEW -lGL -lsfml-graphics -lsfml-window -lsfml-system -ldl -lglfw -lm

Is there a better way to do this?

1

1 Answers

0
votes

Right now I am using subdir-objects where I have to manually specify the paths of each of the source code files for the entire heirarchy.

You have to specify each source file individually, somewhere, in any case.

I had tried using LTLIBRARIES approach using Makefile.am for each of the subdirectories, but for some reason the program does not compile and gives me a lot of undefined reference errors.

I take it that you're talking about building a utility library for each subdirectory. You don't present the Makefile.am file(s) corresponding to this attempt, but among the most likely reasons for the undefined references you describe is that you failed to include all the utility libraries in the link (by listing them at appropriate positions in a_out_LDADD).

The utility library approach makes the most sense when either

  1. your build system is recursive, or
  2. you want to build more than one target from the same sources.

Neither of those is true for the Makefile.am presented in the question. It could be converted to recursive, but there are few enough sources in each subdirectory that that does not seem worthwhile to me. The result would be more complex, not less, along with suffering badly from the issues attending the top-level make not having a complete dependency tree to work with.

Is there a better way to do this?

The Makefile.am presented is similar to what I would use for the source layout described. The changes I would make are mostly stylistic:

AUTOMAKE_OPTIONS = subdir-objects

bin_PROGRAMS = a.out

a_out_SOURCES = \
  EntryPoint.cpp \
  Debug/DebugLog.cpp \
  Debug/DebugLog.h \
  FileIO/FileIO.cpp \
  FileIO/FileIO.h \
  glad/src/glad.cpp \
  glad/include/glad/glad.h \
  ImageLoader/ImageLoader.cpp \
  ImageLoader/stb_image.h \
  Object/Object.cpp \
  Object/Object.h \
  Shader/Shader.cpp \
  Shader/Shader.h \
  Texture/Texture.cpp \
  Texture/Texture.h \
  Window/Window.cpp \
  Window/Window.h
a_out_LDADD = -lGLEW -lGL -lsfml-graphics -lsfml-window -lsfml-system -ldl -lglfw -lm

The one semantic change there is to move the headers from include_HEADERS to a_out_SOURCES. They don't technically need to be listed among the program sources specifically, but that works, and they do need to be listed somewhere lest they be omitted from distributions. They should not be listed in a HEADERS primary, however, because that will cause them to be installed to the system by make install, and that makes sense only for the public headers of a library.

Of less significance, listing each file on its own line and sorting those lines, including putting the headers next to corresponding sources, makes the source list easier to check and maintain. Omitting the unnecessary leading ./ from paths contributes to the same by making those entries easier to read, at least for me, but the distinction between current-directory sources and subdirectory sources is maintained by listing all the current-directory sources first.