I have a directory /src containing all of my source files, and /bin to store all binary after running make command. The directory is something like below:
/BuildDirectory
- - /src
- - /bin
- - configure
- - Makefile.am
- - configure.ac
- - ...
Now in Makefile.am, I have to specified:
bin_PROGRAMS = bin/x bin/y bin/z bin/k ...
bin_x_SOURCES = src/x.cpp
bin_y_SOURCES = src/y.cpp
bin_z_SOURCES = src/z.cpp
Is there any variable that can help to get rid of all "bin/" and "src/" ?
For example I just specify:
$BIN = bin
$SRC = src
And they will look for the correct files in correct folders and compile it to the correct places.
Thanks
You could take advantage of remote building. Place this makefile in the bin dir:
VPATH = ../src
bin_PROGRAMS = x y z k ...
x_SOURCES = x.cpp
y_SOURCES = y.cpp
z_SOURCES = z.cpp
Now replace the current Makefile.am with this one:
SUBDIRS = bin
Now tweak your configure.ac to also generate bin/Makefile
AC_CONFIG_FILES([Makefile
bin/Makefile])
and you should be set for life.
Not to my knowledge. If you're looking to separate your compiled files from your source files, remember that you can build outside of the tree:
$ cd foo-1.2.3
$ mkdir build
$ cd build
$ ../configure
$ make
$ make install
If this is what you're looking to do, you can make the Makefile.am simpler by creating binaries without a directory prefix (and still referencing things in src/ by hand).
If what you're trying to do is what I think you're trying to do, you're trying to achieve something like:
SRCDIR = src
BINDIR = bin
bin_PROGRAMS = $(BINDIR)/x $(BINDIR)/y $(BINDIR)/z
bin_x_SOURCES = $(SRCDIR)/x.cpp
bin_y_SOURCES = $(SRCDIR)/y.cpp
bin_z_SOURCES = $(SRCDIR)/z.cpp
I've tested this a few times in various forms, and it won't compile the code as it would with your example; I somehow convinced it that it was compiling C at one stage:
gmake[1]: *** No rule to make target `bin/x.c', needed by `x.o'. Stop.
I'm thus fairly certain that it's not possible. Sorry.
Related
I have the following command involving qmake:
cd HmiLogging/ && ( test -e Makefile ||\
c:/Users/mureadr/Desktop/A/HMI_FORGF/qt5host/win32/x86/bin/qmake.exe\
C:/Users/mureadr/Desktop/A/HMI_FORGF/src/HmiLogging/HmiLogging.pro\
top_builddir=C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/\
top_srcdir=C:/Users/mureadr/Desktop/A/HMI_FORGF/ -Wall CONFIG+=release\
CONFIG+=qnx_build_release_with_symbols CONFIG+=rtc_build -o Makefile ) &&\
C:/Users/mureadr/Downloads/make-4.2.1/Release/make_msvc.net2003 -f Makefile
qmakegenerates the file Makefile and then regular make is called on that makefile.
The qmake-generated makefile has some entries like so:
deploy_al2hmi-mappings: deploy_fonts
#echo Copying application data... && $(MKDIR)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/al2hmi-mappings"\
&& $(COPY_DIR) $(wildcard C:/Users/mureadr/Desktop/A/HMI_FORGF/src/fordhmi/al2hmi-mappings/*)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/al2hmi-mappings"
deploy_data: deploy_al2hmi-mappings
#echo Copying application data... && $(MKDIR)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/data"\
&& $(COPY_DIR) $(wildcard C:/Users/mureadr/Desktop/A/HMI_FORGF/src/fordhmi/data/*)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/data"
deploy_qml: deploy_data
#echo Copying application data... && $(MKDIR)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/qml" &&\
$(COPY_DIR) $(wildcard C:/Users/mureadr/Desktop/A/HMI_FORGF/src/fordhmi/qml/*)\
"C:/Users/mureadr/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/qml"
You can see that each target depends on the one above it however, examining the recipes you'll also see that the directories created and used are unique to each target!
QUESTION
The generated makefile is chaining those targets, as dependencies, when none actually exists and making it unable to do them in parallel! Why?
I've grep-ed all *.pro and *.pri files - the files that qmake uses to generate makefiles - but deploy_qml doesn't appear in any of them so I'm guessing that these are tasks "internal" to qmake.
Is there any way to tell qmake to NOT dependency-chain them when there is no good reason?
I am new to autotools and have tried to code up an example. I am creating one library and linking it against another object.
My problem is that the Makefile that is generated for the library seems to be mis-interpreted as C code, but is actually C++. If I replace all occurences of ".c" to ".cpp" in the generated Makefile, all is well.
I am using libtool 2.4.2 and autoconf 2.69. My code structure is listed below:
test/
- Makefile.am
- configure.ac
include/
- mylib.hh
src/
hw/
- Makefile.am
- main.cpp
mylib/
- Makefile.am
- mylib.cpp
Below is my top level Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src/mylib src/hw
configure.ac
AC_PREREQ([2.65])
AC_INIT([hw],[1.0.0],[foo.bar#example.com])
# directories (relative to top-level) to look into for AutoConf/AutoMake files
AC_CONFIG_MACRO_DIR([m4])
# enable AutoMake
AM_INIT_AUTOMAKE([1.10])
# all defined C macros (HAVE_*) will be saved to this file
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AM_PROG_CC_C_O
# Check if you have a C++ compiler
AC_PROG_CXX
AC_PROG_CXX_C_O
AC_PROG_INSTALL
## Initialize GNU LibTool
LT_INIT
AC_CONFIG_FILES([Makefile
src/hw/Makefile
src/mylib/Makefile])
AC_OUTPUT
src/hw/Makefile.am
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = hw
hw_SOURCES = main.cpp
AM_CPPFLAGS = -I$(top_srcdir)/include
hw_LDADD = $(top_srcdir)/src/mylib/libmylib.la
src/mylib/Makefile.am
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libmylib.la
libmylib_la_sources = mylib.cpp
libmylib_la_CPPFLAGS = -I$(top_srcdir)/include
The error I get when running make:
make[2]: *** No rule to make target 'libmylib.c', needed by 'libmylib_la-libmylib.lo'. Stop.
Once again, substituting ".cpp" for all occurrences of ".c" in the generated src/mylib/Makefile, the code compiles, links and runs fine. Any help is appreciated.
Did you try changing:
libmylib_la_sources = mylib.cpp
to
libmylib_la_SOURCES = mylib.cpp
(upper case SOURCES)? m4 is case-sensitive.
I have a C++ application which I'm trying to build with scons which consists of several subprograms.
Each subprogram has its own source files in a subdirectory of the source directory. These source files, e.g. source/prog1/prog1.cpp, are compiled into object files which reside in the object directory, e.e. object/prog1/prog1.o.
This works fine since each source directory has its target directory, and there's no possibility of clashes.
However, what I'm trying to do is link these object files into executables, which would be in the same bin directory. So multiple source files (object/prog1, object/prog2, etc) would all go into the same target directory (bin).
The directory layout looks like this:
application
source
prog1
prog1.cpp
something.cpp
prog2
prog2.cpp
somethingelse.cpp
object
prog1
prog1.o
something.o
prog2
prog2.o
somethingelse.o
bin
??? <- what I'm concerned with
I'm trying to achieve that with the following SConstruct script:
env = Environment()
Export('env')
#common objects
common=env.SConscript("source/common/SConscript_object", variant_dir="object/common", duplicate=0)
Export('common')
#sub-programs
env.SConscript("source/prog1/SConscript_bin", variant_dir="bin", duplicate=0)
env.SConscript("source/prog2/SConscript_bin", variant_dir="bin", duplicate=0)
However, scons is complaining with the following error:
scons: *** 'bin' already has a source directory: 'source/prog1'.
The error goes away if I make it so that each subprogram has its own directory in the bin directory, e.g. variant_dir="bin/prog1".
So, my question is this: how can I link object files from multiple sources into the same variant dir?
In your case I would let SCons build the different binaries in their respective folder, and then use the Install builder to copy the binary files to the bin/ directory.
You would get something like:
env = Environment()
Export('env')
common = env.SConscript("source/common/SConscript_object", variant_dir="object/common", duplicate=0)
Export('common')
prog1 = env.SConscript("source/prog1/SConscript_bin", variant_dir="object/prog1", duplicate=0)
prog2 = env.SConscript("source/prog2/SConscript_bin", variant_dir="object/prog2", duplicate=0)
env.Install('bin', prog1)
env.Install('bin', prog2)
With the SConscript of the subprograms being something like
Import('env')
Import('common')
prog1 = env.Program('prog1', [ env.Glob(*.cpp), common ])
Return('prog1')
I think SCons refuses to build different targets into a unique variant directory because variants are designed to build a given target with different build settings, like debug and release mode.
My knowledge of make and autotools (which I'm not yet using for this project) is rudimentary at best despite plenty of googling and experimenting over a long period of time. I have a source hierarchy like below that I'm trying to find way to build has seamlessly as possible.
The application is made up of a main application with source in various subfolders under app/src. These are built with the respective Makefile in the root of that folder.
Then I have multiple other utilities that reside different folders under app/tools that each have their own Makefile.
app/src/module1/file1.cpp
app/src/module1/file1.hpp
app/src/module2/file2.cpp
app/src/module2/file2.hpp
app/src/module3/file3.cpp
app/src/module3/file3.hpp
app/src/main.cpp
app/src/main.hpp
app/src/Makefile
app/tools/util1/file1.cpp
app/tools/util1/file1.hpp
app/tools/util1/Makefile
app/tools/util2/file2.cpp
app/tools/util2/file2.hpp
app/tools/util2/Makefile
The problem for me is that some of these tools depend on source files inside the app/src source folder, but with a preprocess macro EXTERNAL_TOOL enabled. So the object files generated from compiling the main app and the varous utilities are not compatible.
Currently to build each portion of the project I'm having to clean the source tree in between. This is painful and certainly not what I want in the end. What would be the best way to go about solving this? Ideas I've had that I've no been able to put into practice are:
Separate build directory for each portion of the project
When building the external tools, tagging their object files in the main app source tree somehow (util.file1.o?)
I'm not too sure I have the time and patience needed to master make / autotools. Might one of the other build tools (scons? cmake?) make this kind of task easier to accomplish? If so which one?
UPDATE: This is what I've got now
SOURCES := util1.cpp util2.cpp util3.cpp \
../../src/module1/file1.cpp \
../../src/module1/file2.cpp \
../../src/module1/file3.cpp \
../../src/module2/file4.cpp \
../../src/module3/file5.cpp \
../../src/module3/file6.cpp \
../../src/module4/file7.cpp \
../../src/module4/file8.cpp \
../../src/module3/file9.cpp \
../../src/module4/file10.cpp \
../../src/module5/file11.cpp \
../../src/module3/file12.cpp \
../../src/module1/file13.cpp \
../../src/module3/file14.cpp \
../../src/module3/file15.cpp
OBJECTS = $(join $(addsuffix .util/, $(dir $(SOURCES))), $(notdir $(SOURCES:.cpp=.o)))
.PHONY: all mkdir
all: util
util: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) $(LIBS) -o util
$(OBJECTS): | mkdir
$(CXX) -c $(CXXFLAGS) -o $# $(patsubst %.o,%.cpp,$(subst .util/,,$#))
mkdir:
#mkdir -p $(sort $(dir $(OBJECTS)))
clean:
-#rm -f $(OBJECTS) util
-#rmdir $(sort $(dir $(OBJECTS))) 2>/dev/null
I came about this after extensive googling SO browsing. This seems to work, but this part doesn't really seem particular nice (feels like a bit of a hack):
$(OBJECTS): | mkdir
$(CXX) -c $(CXXFLAGS) -o $# $(patsubst %.o,%.cpp,$(subst .util/,,$#))
In particular I'm not too keen on the fact I'm creating the list of objects from sources earlier on and adding the suffix, only to do the reverse down here. I couldn't seem to get it working any other way.
CMake has add_definitions and remove_definitions commands. You can use them to define macros for different parts of your project:
# building tools #
add_definitions(-DEXTERNAL_TOOL)
add_subdirectory($TOOL1$ $BUILD_DIR$)
add_subdirectory($TOOL2$ $BUILD_DIR$)
...
# building main app #
remove_definitions(-DEXTERNAL_TOOL)
add_executable(...)
This can be done with SCons rather painlessly. You will definitely need a build directory hierarchy for the objects built with different preprocessor macros. In SCons terms, creating build directories like this is called variant_dir. I would recomend the following SCons Hierarchical build structure:
app/SConstruct
app/src/module1/file1.cpp
app/src/module1/file1.hpp
app/src/module2/file2.cpp
app/src/module2/file2.hpp
app/src/module3/file3.cpp
app/src/module3/file3.hpp
app/src/main.cpp
app/src/main.hpp
app/src/SConscript_modules
app/src/SConscript_main
app/tools/util1/file1.cpp
app/tools/util1/file1.hpp
app/tools/util2/file2.cpp
app/tools/util2/file2.hpp
app/tools/SConscript
app/build/main/
app/build/target1/modules/
app/build/target2/modules/
app/build/tools/utils/
To be able to build the same source files with different preprocessor macros, you will need to build the same file with several different Environments. These env's could be setup in the src/module SConscript scripts, or from the root SConstruct and passed down. I prefer the second option, since it will make the src/module SCons scripts modular, and unaware (agnostic) of the preprocessor macros.
Here is the root build script, which creates the different env's and orchestrates the sub-directory build scripts:
app/SConstruct
defines1 = ['MACRO1']
defines2 = ['MACRO2']
env1 = Environment(CPPDEFINES = defines1)
env2 = Environment(CPPDEFINES = defines2)
includePaths = [
'src/module1',
'src/module2',
'src/module3',
]
env1.Append(CPPPATH = includePaths)
env2.Append(CPPPATH = includePaths)
# Build different versions of the module libs
SConscript('src/SConscript_modules',
variant_dir = '#build/target1/modules',
exports = {'env':env1},
duplicate=0)
SConscript('src/SConscript_modules',
variant_dir = '#build/target2/modules',
exports = {'env':env2},
duplicate=0)
# Build main with env1
SConscript('src/SConscript_main',
variant_dir = '#build/main',
exports = {'env':env2},
duplicate=0)
# Build tools with env2
SConscript('tools/SConscript',
variant_dir = '#build/utils',
exports = {'env':env2},
duplicate=0)
This is the build script for main
app/src/SConscript_main
Import('env')
sourceFiles = ['main.cpp']
# If you want to modify the env here, Clone() it first, otherwise
# the changes will be visible to all other SConscripts
env.Program(target = 'main', source = sourceFiles)
This is the build script for the module libs, it will be called twice, each time with a different env
app/src/SConscript_modules
Import('env')
module1SourceFiles = ['file1.cpp']
module2SourceFiles = ['file2.cpp']
module3SourceFiles = ['file3.cpp']
# If you want to modify the env here, Clone() it first, otherwise
# the changes will be visible to all other SConscripts
env.Library(target = 'module1', source = module1SourceFiles)
env.Library(target = 'module2', source = module2SourceFiles)
env.Library(target = 'module3', source = module3SourceFiles)
I'm struggling to write Makefiles that properly build my unit tests. As an example, suppose the file structure looks like this
src/foo.cpp
src/foo.hpp
src/main.cpp
tests/test_foo.cpp
tests/test_all.cpp
So, to build the executable test_all, I'd need to build test_foo.o which in turn depends on test_foo.cpp but also on src/foo.o.
What is the best practice in this case? One Makefile in the parent folder? One Makefile per folder? If so, how do I manage the dependencies across folders?
Common practice is a Makefile per directory. That's what I would have suggested before I read "Recursive Make Considered Harmfull" (http://miller.emu.id.au/pmiller/books/rmch/). Now I'd recommend one Makefile. Also check out the automatic dependency generation - now you don't even need to work out what your tests depends on. All you need is some targets.
The common practice is one Makefile for each folder. Here is a simple Makefile.am script for the root folder:
#SUBDIRS = src tests
all:
make -C ./src
make -C ./tests
install:
make -C ./src install
uninstall:
make -C ./src uninstall
clean:
make -C ./src clean
test:
make -C ./tests test
The corresponding Makefile.am for the src folder will look like this:
AM_CPPFLAGS = -I./
bin_PROGRAMS = progName
progName_SOURCES = foo.cpp main.cpp
LDADD = lib-to-link
progName_LDADD = ../libs/
Makefile.am for tests will look similar:
AM_CPPFLAGS = -I../src
bin_PROGRAMS = tests
tests_SOURCES = test_foo.cpp test_all.cpp
Use automake to generate Makefile.in files from the .am files. The configure script will use the .in files to produce the Makefiles. (For small projects you would like to directly hand-code the Makefiles).