I am able to build googletest and use it to run unit tests.
In MY makefile for my unit_test.cpp, I need to check whether googletest libs exist in ..\googletest\ and only if they do not exist, I want to run cmake and make for googletest.
Running cmake and make even if they are built takes 30 secs so I only want to run cmake and make if I actually have to.
QUESTION
In MY makefile for my unit_test.cpp, what could I list as a dependency so that building googletest only happens if actually necessary?
A "brute force" approach would be to list googletest\build\lib\libgtest.a but this would break if, however unlikely, googletest changes the output name from lib\ to libs\.
If you are worried about possible change of the file layout in the build directory, you can use cmake --install command and directly specify the subfolders for header files and libraries before running cmake configure step. CMAKE_INSTALL_PREFIX variable allows to specify install directory and CMAKE_INSTALL_INCLUDEDIR, CMAKE_INSTALL_LIBDIR variables allow to specify subfolders for header files and libraries, accordingly:
GOOGLETEST_SRC_DIR := googletest
GOOGLETEST_BUILD_CACHE_DIR := googletest_build_cache
GOOGLETEST_SDK_DIR := googletest_sdk
GOOGLETEST_SDK_INCLUDE_DIR := include
GOOGLETEST_SDK_LIB_DIR := lib
GOOGLETEST_LIB := gtest
GOOGLETEST_MAIN_LIB := $(GOOGLETEST_LIB)_main
UT := ut
UT_SRC := ut.cpp
default_target: $(UT)
$(GOOGLETEST_BUILD_CACHE_DIR) :
cmake \
-DCMAKE_INSTALL_PREFIX=$(shell pwd)/$(GOOGLETEST_SDK_DIR) \
-DCMAKE_INSTALL_LIBDIR=$(GOOGLETEST_SDK_LIB_DIR) \
-DCMAKE_INSTALL_INCLUDEDIR=$(GOOGLETEST_SDK_INCLUDE_DIR) \
-B $(GOOGLETEST_BUILD_CACHE_DIR) -S $(GOOGLETEST_SRC_DIR)
cmake --build $(GOOGLETEST_BUILD_CACHE_DIR) --parallel
touch $(GOOGLETEST_BUILD_CACHE_DIR)
$(GOOGLETEST_SDK_DIR): $(GOOGLETEST_BUILD_CACHE_DIR)
cmake --install $(GOOGLETEST_BUILD_CACHE_DIR)
touch $(GOOGLETEST_SDK_DIR)
$(UT): $(UT_SRC) $(GOOGLETEST_SDK_DIR)
g++ $(UT_SRC) -o $(UT) \
-I$(GOOGLETEST_SDK_DIR)/$(GOOGLETEST_SDK_INCLUDE_DIR) \
-L$(GOOGLETEST_SDK_DIR)/$(GOOGLETEST_SDK_LIB_DIR) \
-l$(GOOGLETEST_MAIN_LIB) -l$(GOOGLETEST_LIB)
clean:
rm -f $(UT)
rm -fR $(GOOGLETEST_BUILD_CACHE_DIR) $(GOOGLETEST_SDK_DIR)
Related
I am integrating my own Qt app into buildroot. *.mk file follows.
CATCHER_SITE=http://g7/gitlab/igorsk/catcher.git
CATCHER_SITE_METHOD=git
CATCHER_VERSION=master
CATCHER_DEPENDENCIES=qt
ifeq ($(BR2_PACKAGE_QT5),y)
CATCHER_QMAKE = $(QT5_QMAKE)
else
CATCHER_QMAKE = $(QT_QMAKE)
endif
define CATCHER_CONFIGURE_CMDS
(cd $(#D); $(TARGET_MAKE_ENV) $(CATCHER_QMAKE))
endef
define CATCHER_BUILD_CMDS
$(TARGET_MAKE_ENV) $(MAKE) -C $(#D)
endef
define CATCHER_INSTALL_TARGET_CMDS
$(TARGET_MAKE_ENV) $(MAKE) INSTALL_ROOT=$(TARGET_DIR) -C $(#D) install
endef
$(eval $(generic-package))
The app compiles, but it doesn't get installed to a target directory (and therefore to resulting rootfs ). During buildroot's "Installing to target" phase I get Nothing to be done for 'install'. message. buildroot/output/build/catcher-master/Makefile has emtpy install rule.
Buildroot 2015.08.1
Qt 4.8.7
The question is: why is this happening and how do I get my app installed to target?
For a university project we made an OpenGL application which uses Qt for the GUI. When I use qmake -spec macx-g++ project.pro I can make a Makefile, and if I then do make it correctly makes the application. However, when I then send the complete folder to the other person in the project and he does make he gets the error
Makefile:209: warning: overriding commands for target `moc_window.cpp'
Makefile:203: warning: ignoring old commands for target `moc_window.cpp'
make: *** No rule to make target `/usr/lib64/qt-3.3/mkspecs/default/qmake.conf', needed by `Makefile'. Stop.
However, when in the same folder he does qmake; make it does work correctly. The problem is that when handing the code in we don't know if the professor has qmake available, so we would like it to work by only using make. Are we missing something that should be addded to have the Makefile made with qmake work, without having to do qmake again? Our .pro file is below.
TEMPLATE = app
TARGET = smoke
QT = core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
SOURCES += \
fluids.cpp \
simulation.cpp \
visualization.cpp \
window.cpp \
myglwidget.cpp \
vector.cpp \
grid.cpp \
scalar.cpp
HEADERS += \
window.h \
myglwidget.h \
simulation.h \
vector.h \
grid.h \
visualization.h \
scalar.h
INCLUDEPATH += fftw-2.1.5/include /usr/local/include include
LIBS += -L"$$_PRO_FILE_PWD_/fftw-2.1.5/lib" -lrfftw -lfftw -framework OpenGL -framework GLUT -stdlib=libc++
QMAKE_CXXFLAGS += -stdlib=libc++
QMAKE_CXXFLAGS += -std=c++11
FORMS += \
window.ui
The build directory is not portable. It is only ever meant to work on the system where you executed qmake, and for the particular Qt install that you ran qmake from. Recall that each Qt install has its own qmake, so e.g. if you have three Qt versions, each provides its own qmake that you must use to build a project using that version.
The project you ship should contain the .pro file, the sources, and whatever else the build calls for, like icon files, resources, etc.
The recipient, to build it, should:
Create a build folder.
cd into the build folder.
qmake /path/to/sources/project.pro && make -j
That's how you distribute and build Qt projects.
why does qmake not build the application directly?
Why do you not make your own shoes? The reasons are the same. Don't reinvent the wheel.
Of course, engineers sometimes have an itch to scratch. Enter Qt Build System (qbs). If your project's build is given as a .qbs file, then you do:
Create a build root folder.
cd into the build root folder.
qbs -f /path/to/sources/project.qbs - this builds the project.
I'm working on some bare-metal embedded code that runs on ARM, and thus has to deal with the whole ARM vs. THUMB mode distinction. The current build system uses static pattern rules to determine whether to compile files in ARM or THUMB mode.
$(ACOBJS) : %.o : %.c
#echo
$(CC) -c $(CFLAGS) $(AOPT) -I . $(IINCDIR) $< -o $#
$(TCOBJS) : %.o : %.c
#echo
$(CC) -c $(CFLAGS) $(TOPT) -I . $(IINCDIR) $< -o $#
Where ACOBJS is a list of output objects that should be in ARM mode and the same for TCOBJS and Thumb mode. These lists are created from the list of sources in the usual manner of
ACOBJS = $(ACSRC:.c=.o)
TCOBJS = $(TCSRC:.c=.o)
Currently this results in the object files from the build being strewn about the source tree, which I don't particularly desire. I've been trying to set this up for out of tree builds but haven't been able to get this to work. I don't necessarily need to get full out of tree builds working, but I would like to at least be able to use an output directory under which all the intermediate files end up going. What is the best strategy to achieve this under these constraints?
One option I'm considering is using either automake or the whole autotools toolchain to build a makefile. This would seem to support creating the type of makefile I want, but seems like overkill. It also seems like there would be an inherent impedance mismatch between autotools, which is designed for portable builds, and bare-metal embedded systems, where things like host tuple are dictated by the target micro.
This is a bit old but I was just trying to do the same thing this was the first google hit. I thought it was worth sharing another approach since neither answer is convenient if you're not using autotools and want to be able to build in any directory with a single command and later just blow away that directory.
Here's an example of a Makefile that refers to files relative to the directory containing the Makefile.
MAKEFILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
MFD := $(MAKEFILE_DIR)
CXX=g++
CXXFLAGS=-std=c++14 -Wall -Wextra -pedantic -c
test: test.o adjacency_pointers_graph.o
$(CXX) $^ -o $#
%.o: $(MFD)/%.cpp $(MFD)/adjacency_pointers_graph.h
$(CXX) $(CXXFLAGS) $< -o $#
Then to do an sort of source build:
mkdir build
cd build
make -f ../Makefile
Considering/assuming you don't care about portability and are using GNU make, you can use the VPATH feature:
Create the directory where you want to do your build.
Create a 'Makefile' in that directory with (approximately) the following contents:
path_to_source = ..
VPATH = $(path_to_source)
include $(path_to_source)/Makefile
Change the path_to_source variable to point to the root of your source tree.
Additionally you probably need to tweak your original Makefile to make sure that it supports the out of source build. For example, you can't reference to prerequisites from your build rules and instead must use $^ and $<. (See GNU make - Writing Recipes with Directory Search) You might also need to modify the vpath-makefile. For example: adding CFLAGS+=-I$(path_to_source) might be useful.
Also note that if a file is in both your source and build directory, make will use the file in your build directory.
On automake
If you use automake, you're pretty much using the entire autotools. automake cannot work without autoconf.
The Makefiles generated by automake support out-of-source builds and cross-compilation, so you should be able to create subdirectories arm/ and thumb/ and run ../configure --host=arm-host-prefix in arm/ and run ../configure --host=thumb-host-prefix in thumb/. (I don't know the actual host tuples that you'd use for each compiler.)
Using GNU make
Since you're using GNUMake, you could do something like this:
ACOBJS := $(addprefix arm/,$(ACSRC:.c=.o))
TCOBJS := $(addprefix thumb/,$(TCSRC:.c=.o))
Use something like this answer to ensure that the arm/ and thumb/ directories (and any subdirectories) exist.
For those unfamiliar with IDL (interface description language), it abstracts data description for use across platforms (java, c, c++, etc). My project has dependencies Foo.c, Foo.h, FooHelper.c, and FooHelper.h which are generated from Foo.idl. How do I run an arbitrary command when Foo.idl changes, but still include Foo.c, FooHelper.c, in the build process?
My current attempts add a rule to the Makefile.am -- the hope is that the rule is copied over to the generated Makefile.
I have tried:
Foo.idl : Foo.idl
${the_generate_command}
and then added Foo.idl to my_program_SOURCES but it doesn't run the_generate_command when building.
I have had success generating from the IDL with
Foo.c Foo.h FooHelper.h FooHelper.c : Foo.idl
${the_generate_command}
But it won't add Foo.c, FooHelper.c to the compile process, so they're never built, just generated by the_generate_command!
All the code (including the idl) is in $PROJECT_DIR/src.
rq's answer is almost correct, but misses a couple of subtleties. Try this:
bin_PROGRAMS = myprogram
myprogram_SOURCES = Foo.c Foo.h FooHelper.h FooHelper.c $(OTHER_SOURCES)
BUILT_SOURCES = Foo.c Foo.h FooHelper.h FooHelper.c
EXTRA_DIST = Foo.idl
MAINTAINERCLEANFILES = Foo.c Foo.h FooHelper.h FooHelper.c
Foo.c: Foo.idl
$(THE_GENERATE_COMMAND)
Foo.h FooHelper.h FooHelper.c: Foo.c
#if test -f $#; then \
touch $#; \
else \
## Recover from the removal of $#
rm -rf $<; \
$(MAKE) $(AM_MAKEFLAGS) $<; \
fi
The additional rules to "generate" Foo.h, FooHelper.h and FooHelper.c from Foo.c ensure that parallel builds won't try and run $(THE_GENERATE_COMMAND) twice. It is an idiom detailed in the Automake manual which will work for parallel builds. There is still a little fragility here: if the user removes (say) FooHelper.h and FooHelper.c and starts a parallel make, it may run the $(MAKE) $(AM_MAKEFLAGS) $< recovery part of the rule multiple times in parallel. As the manual says, this race can only going to happen if the user manually mutilates the build tree, and even then it's nothing a make clean; make cannot fix.
The BUILT_SOURCES line ensures that Foo.c, Foo.h, FooHelper.h and FooHelper.c are built before trying to build myprogram (see this section of the Automake manual to see why just adding them to myprog_SOURCES is insufficient). The EXTRA_DIST variable ensures that the .idl file will be captured by make dist (reference).
MAINTAINERCLEANFILES specifies additional files to delete when running make maintainer-clean; this is to comply with the GNU Makefile Standards. See also the variable's description in the Automake manual.
I am using cmake to build my project. For UNIX, I would like to type make from my project's root directory, and have cmake invoked to create the proper Makefiles (if they don't exist yet) and then build my project. I would like the cmake "internal" files (object files, cmake internal Makefiles, etc.) to be hidden (e.g. put in a .build directory) so it doesn't clutter my project directory.
My project has several sub-projects (in particular, a library, a user executable, and a unit test executable). I would like Makefiles (i.e. I type make and this happens) for each sub-project to execute cmake (as above) and build only that sub-project (with dependencies, so the library would be built from the executables' Makefiles, if needed). The resulting binary (.so library or executable) should be in the sub-project's directory.
I made a Makefile which does the main project bit somewhat well, though it feels somewhat hackish. I can't build specific targets using it, because my Makefile simply calls make in cmake's build directory.
Note that because the library is a sole dependency (and probably doesn't need to be build manually, and because I'm lazy) I omitted it in my Makefile.
BUILD_DIR := .build
.PHONY: all clean project-gui ${BUILD_DIR}/Makefile
all: project-gui project-test
clean:
#([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean && rm -r ${BUILD_DIR}) || echo Nothing to clean
project-gui: ${BUILD_DIR}/Makefile
#make -C ${BUILD_DIR} project-gui
#cp ${BUILD_DIR}/project-gui/project-gui $#
project-test: ${BUILD_DIR}/Makefile
#make -C ${BUILD_DIR} project-test
#cp ${BUILD_DIR}/project-test/project-test $#
${BUILD_DIR}/Makefile:
#[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}
#[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CMAKE_OPTS} ..)
If it helps, here's my project structure (if this is "wrong" please tell me -- I'm still learning cmake):
project/
project/CMakeLists.txt
project/common.cmake
project/Makefile -- see Makefile above for this; should be replaced with something better, building libproject, project-gui, and project-test
project/libproject/
project/libproject/CMakeLists.txt
project/libproject/libproject.so -- after build
project/libproject/Makefile -- doesn't exist yet; should build libproject only
project/libproject/source/
project/libproject/include/
project/project-gui/
project/project-gui/CMakeLists.txt
project/project-gui/Makefile -- doesn't exist yet; should build libproject then project-gui
project/project-gui/source/
project/project-gui/include/
project/project-test/
project/project-test/CMakeLists.txt
project/project-test/Makefile -- doesn't exist yet; should build libproject then project-test
project/project-test/source/
project/project-test/include/
If you haven't caught on yet, I'm basically looking for a way to build the project and sub-projects as if cmake wasn't there: as if my project consisted of only Makefiles. Can this be done? Is the solution elegant, or messy? Should I be trying to do something else instead?
Thanks!
If cmake is generating the makefiles, you can simply include the generated makefile in the master makefile, eg
# makefile
all: # Default
include $GENERATED
$GENERATED:$CMAKEFILE
# Generate the makefile here`
The included files are generated then make is restarted with the new included files. The included files should detail the targets, etc.
You should be able to change the location of used files using the vpath directive, see e.g. the Gnu make manual,
vpath %.o project/.build
else the tedious way is to rewrite the rules making note of the necessary directory.
Ed:
Perhaps we shouldn't use a flat makefile.
Try something like:
# makefile
all: gui test
clean:
$(MAKE) -f $(GUI-MAKE) clean
$(MAKE) -f $(TEST-MAKE) clean
gui:$(GUI-MAKE)
$(MAKE) -f $(GUI-MAKE) all
$(GUI-MAKE):$(GUI-CMAKE)
# Generate
# Same for test
This should work if the $(MAKE) -f $(GUI-MAKE) all command works on the command line, and we've hidden cmake in the generating target. You would have to copy any other targets to the master makefile as well, and take care running make in parallel.
Propagating object files through should involve something like
%.o:$(GUI-MAKE)
$(MAKE) -f $(GUI-MAKE) $#
although you'll probably get errors trying to make test objects