Phony targets not working on windows make - c++

I am trying to make a phony target on make so that my "all" target doesn't run every time even if the prerequisite files haven't changed, but make still runs every target every time I run it.
Here is an example Makefile:
CXX = g++
CXXFLAGS = -Wall
.PHONY: all
all: testing testing2
testing: testing.cpp
testing2: testing2.cpp
clean:
del *.exe *.o
The due to declaring all as a phony target using .PHONY, the intended result is that by running make, the "testing" and "testing2" targets should only be ran if their respective results (testing.exe and testing2.exe) are older than their prerequisites (testing.cpp and testing2.cpp). However, every time make is run, both targets are ran as well. I am using make on windows installed via chocolatey, make --version is GNU Make 4.3 Built for Windows32.
Do phony targets not work on make windows?

Your rules say you'll build the files testing and testing2. But your recipes don't build those files, they build the files testing.exe and testing2.exe.
So when make runs, it looks for the file testing to see if it's up to date and it doesn't exist, so make runs the recipe, which builds testing.exe. Then the next time make runs, it looks for the file testing to see if it's up to date and it doesn't exist, so make runs the recipe, which builds testing.exe. Etc. etc.
This has nothing to do with PHONY which only applies to all so why would it be related to rebuilding testing?
You need to name your targets in make with the same name of the file that your recipe creates.

Related

Makefile deferred compilation

I have a simple makefile with a variable for the compiler flags, it also contains some targets that modify that variable and append some flags.
My point with it is to be able to run, for example:
make debug perf
that would in turn add to the variable the flags required to build under that configuration. The problem is that if I run it, it does compile the executable with the debug info, and then tries to compile with the performance tools, and obviously does nothing. Can make only execute the compilation step after both targets run?
Makefile:
CFLAGS = -std=c11 -Wall -pedantic -D_GNU_SOURCE
executable: gcc $(CFLAGS) main.c -o exe
debug: CFLAGS += -g
debug: executable
perf: CFLAGS += -D__PERF__
perf: executable
Make version 4.2.1
One approach is to have different executable files for different flag combinations, ie
executable # default to release build
executable.dbg # with -g
executable.perf # with -D__PERF__
executable.dbgperf # with both
The two advantages are
you're never unsure how some executable file was built, and you never accidentally test the wrong thing / waste time trying to debug something with no debug symbols, etc.
Make's file dependency logic actually works correctly
This does assume you have a manageable number of flag combinations. If there are too many, the profusion of targets may make your Makefile impractical.
I exactly have the same requirements! :-) As this, I compile my executables with all the options in the filename like: myprog-debug-coverage and so on. All the object files goes to a directory like build-myprog-debug-coverage as example. All this has the advantage that there is no need to recompile all if you need it once for debug, do a change and compile for coverage and after next change for debug again.
The first thing you must do is to filter out all non-targets which are needed for the options like debug with:
debug:
#:
to simply do nothing.
In addition, you filter out the non-targets with something like:
export FOUND_ACTIONS=$(filter $(ACTIONS), $(MAKECMDGOALS))
and process these variables later on into the flags you need for compilation like:
$(eval $(call CHECK_FOR_CMDGOAL,debug,export LCXXFLAGS+= -DDEBUG -DGDB_HELPER -g,build_dir_ext=$(build_dir_ext)-debug))
and after that you can write your standard recipes with the found flags from the variables.
I can't give you a ready to use Makefile here as my one is a bit larger while processing a lot of flags like different compilers, memory debug libraries as efence, build for coverage and much more.
I'm in hope that you can catch the idea how to process the pseudo targets for flags and the real targets and how a Makefile can split both.
And yes, that is not how a Makefile works typically. But I believe it is really convenient at the end of the day. Giving manual CXXFLAGS and so on did not the job, as you as a user have a complete list of flags, libs and options on the comand line, which is a nightmare.
This makes no sense to me. Why would you want to compile file(s) as debug, generating a program executable that is built with debug, then in the same make command recompile the same file(s) with optimization, generating a program executable that is built with optimization.
In a single directory there can be only one file named executable, so how can you build the same file twice and have two different versions at the same time? How do you intend to run the debug executable versus the perf executable?
You either need to build different files, or you need to build them into different directories (one for debug and one for perf). I recommend the latter.
But to answer your specific question: it is not possible in make to build the same target multiple different times in the same invocation of make. Once a single make invocation tries to build a target named foo, it will never try to build that target again no matter how many other targets might list it as a prerequisite. If you re-run make again, it will try again to build foo (one time).

Generate a source file that may or may not be updated

I have a CMakeLists.txt in which I want to generate several source files (namely, versiondata.cpp and version.rc.inc, included by res.rc) that depends on the general environment (current git HEAD, gcc -v output, CMakeCache.txt itself, and so on).
If it depended just on some files, I would generate it using an add_custom_command directive with the relevant DEPENDS and OUTPUT clauses; however, it's a bit tricky to pinpoint exactly its file dependencies; ideally, I'd want to run my script every time I call make, updating the files only if needed; if the generated files have actually been touched, then the targets depending from them should be rebuilt (the script is careful not to overwrite the files if they would have the same content as before).
My first attempt was using an add_custom_command with a fake main output, like this:
add_custom_command(OUTPUT versiondata.cpp.fake versiondata.cpp version.rc.inc
COMMAND my_command my_options
COMMENT "Generating versiondata.cpp"
)
# ...
# explicitly set the dependencies of res.rc, as they are not auto-deduced
set_source_files_properties(res.rc PROPERTIES OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/version.rc.inc;${PROJECT_SOURCE_DIR}/other_stuff.ico")
# ...
add_executable(my_executable WIN32 ALL main.cpp versiondata.cpp res.rc)
versiondata.cpp.fake is never really generated, so the custom command is always run. This worked correctly, but always rebuilt my_executable, as CMake for some reasons automatically touches the output files (if generated) even though my script left them alone.
Then I thought I might make it work using an add_custom_target, that is automatically "never already satisfied":
add_custom_target(versiondata BYPRODUCTS versiondata.cpp version.rc.inc
COMMAND my_command my_options
COMMENT "Generating versiondata.cpp"
)
# ...
# explicitly set the dependencies of res.rc, as they are not auto-deduced
set_source_files_properties(res.rc PROPERTIES OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/version.rc.inc;${PROJECT_SOURCE_DIR}/other_stuff.ico")
# ...
add_executable(my_executable WIN32 ALL main.cpp versiondata.cpp res.rc)
The idea here is that the versiondata target should be "pulled in" from the targets that depend on its BYPRODUCTS, and should be always executed. This seems to work on CMake 3.20, and the BYPRODUCTS seem to have some effect because if I remove the dependencies from my_executable my script doesn't get called.
However, on CMake 3.5 I get
make[2]: *** No rule to make target 'version.rc.inc', needed by 'CMakeFiles/my_executable.dir/res.rc.res'. Stop.
and if I remove the explicit dependency from version.rc.inc it doesn't get generated at all
[ 45%] Building RC object CMakeFiles/my_executable.dir/res.rc.res
/co/my_executable/res.rc:386:26: fatal error: version.rc.inc: No such file or directory
#include "version.rc.inc"
^
compilation terminated.
/opt/mingw32-dw2/bin/i686-w64-mingw32-windres: preprocessing failed.
CMakeFiles/my_executable.dir/build.make:5080: recipe for target 'CMakeFiles/my_executable.dir/res.rc.res' failed
make[2]: *** [CMakeFiles/my_executable.dir/res.rc.res] Error 1
so I suspect that the fact that this works in 3.20 is just by chance.
Long story short: is there some way to make this work as I wish?
In CMake there are two types of dependencies:
Target-level dependency, between targets.
A target can be build only after unconditional building of all targets it depends on.
File-level dependency, between files.
If some file is older than one of its dependencies, the file will be regenerated using corresponded COMMAND.
The key factor is that checking for timestamp of dependent files is performed strictly after building of dependent targets.
For correct regeneration of versiondata.cpp file and executable based on it, one need both dependencies:
Target-level, which would ensure that versiondata custom target
will be built before the executable.
add_dependencies(my_executable versiondata)
File-level, which will ensure that the executable will be rebuilt whenever
file versiondata.cpp will be updated.
This dependency is created automatically by listing versiondata.cpp
among the sources for the executable.
Now about BYPRODUCTS.
Even without explicit add_dependencies, your code works on CMake 3.20 because BYPRODUCTS generates needed target-level dependency automatically.
This could be deduced from the description of DEPENDS option in add_custom_target/add_custom_command:
Changed in version 3.16: A target-level dependency is added if any dependency is a byproduct of a target or any of its build events in the same directory to ensure the byproducts will be available before this target is built.
and noting, that add_executable effectively depends on every of its source files.
Because given comment for DEPENDS is applicable only for CMake 3.16 and later,
in older CMake versions BYPRODUCTS does not create target-level dependency automatically, and one need to resort to explicit add_dependencies.

Merging make and cmake's make into build system

I have to merge cmake's makes and makes in our build systems. The build systems are supposed to be able to work with both options make and cmake. The problem is that cmake's make exports do not contain all variables and settings, which need to be set as make in our build systems. Basically, we use three complicated build systems for cross platform development and I do not like setting everything on many places, because then it is hard to maintain the system like that.
E g. makefiles from many coders in all build system contains include common file like:
include $(PROJECT_CONF_DIR)/common/something.mk
How to solute it by cmake? I do not like modifying coders' CMakeLists.txt (max. one row solution for them) and I also do not like modifying cmake exports into make files.
Basically, I need to put somewhere in cmake command or cmake's export (the best) some link which will lead to include all 'garbage' expecting by our build tool chains.
Make sure that CMakeLists.txt can contain many cmake subprojects and libraries.
e.g. Our build system from makefiles contains something like:
directories-default:
mkdir -p $(BUILD_DIR)
mkdir -p $(OBJ_DIR)
I need to implement it somehow in cmake include.
To be able to run make directories-default after configuration, you have to create a target. You can make a target that will call a custom command, which would run the shell commands you need.
add_custom_target(directories-default COMMAND mkdir -p "dir1" COMMAND mkdir -p "dir2")
The syntax above will result in a target that is always considered out of date, ie every time you run make directories-default (or make all), the commands will be executed. If you don't want to re-run the command every time you can use a custom command:
add_custom_command(OUTPUT "dir3" "dir4" COMMAND mkdir -p "dir3" COMMAND mkdir -p "dir4")
add_custom_target(directories-default2 DEPENDS "dir3" "dir4")
Here make directories-default2 will only run the commands the first time you run it. You can also create a dependency chain of commands using the DEPENDS argument in add_custom_command.

How can I use Google Test with my project that builds via autotools?

It seems like there are a few answers that kind-of, sort-of make sense, but that I don't know how to carry out. And I haven't found a comprehensive answer.
The First Problem
Google Test should not be an installed library, it should be built with the project. (See the FAQ.) As far as I can tell, this means the Google Test libraries are a dependency of my unit tests, and should be built when I run "make check" within my project for the first time. This should build Google Test libraries in some directory. I don't know how to do this. It mentions some autotools script that's deprecated, and I'm not sure what they're talking about or how to point my build at it properly.
The Second Problem
Assuming the build is successful, how do I write a test that uses my locally-compiled version of Google Test to run tests? I assume that there are a bunch of Makefile.am commands I put in my tests directory. But what are they? And what's an example of a unit test that uses Google Test?
I have solved the problem to my satisfaction! I will move on entirely now. This is basically asking for a tutorial. There are a lot of decisions that must be made, hopefully logically, so that Google Test dovetails nicely into autotools. So I apologize in advance for the long answer, but all the details should be there.
The First Problem
In order to understand the answer, the question needs to be rephrased a little. We are compiling Google Test as a library which our test code will link to. The library will not be installed. The question we want to ask is
"How do we configure autotools to compile Google Test as a library
which our test code can link against?"
In order to do that, we need to download Google Test and place it into our project. I use Github, so I do that by adding a submodule in the root path of my project:
$ git submodule add git#github.com:google/googletest.git
$ git submodule init
$ git submodule update
This downloads googletest into my root of my project:
/:
Makefile.am
configure.ac
src/:
(files for my project)
tests/:
(test files)
googletest/:
googletest/:
include/:
(headers, etc., to be included)
gtest/:
gtest.h
m4/:
(directory for m4 scripts and things)
src/:
(source files for Google Test)
I need to compile per the instructions. I only want the Google Test library to be built upon running make check, so I will use check_LTLIBRARIES. I add the following to my tests Makefile.am in /tests:
check_LTLIBRARIES = libgtest.la
libgtest_la_SOURCES = ../googletest/googletest/src/gtest-all.cc
libgtest_la_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest
libgtest_la_LDFLAGS = -pthread
This requires subdir-objects to be enabled in configure.ac. That is accomplished by adding it to the AM_INIT_AUTOMAKE line. I also need to include the makefile in AC_CONFIG_FILES. We also want to use libtool, because we are compiling library files (I'll explain why and how that works in a moment). To use libtool, we add AM_PROG_AR, LT_INIT. We want autoreconf to install m4 macros to /m4, and then we want automake to find them, so we need AC_CONFIG_MACRO_DIRS. My configure.ac has lines updated:
AM_INIT_AUTOMAKE([-Wall -Werror subdir-objects])
...
AM_PROG_AR
LT_INIT
AC_CONFIG_MACRO_DIRS([m4])
...
AC_CONFIG_FILES([Makefile
src/Makefile
tests/Makefile
])
I also need to include the subdirectory and a line pointing to the macros in the /m4 macros directory in my /Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src tests
What has this done? Libtool has been enabled with AM_PROG_AR and LT_INIT. The check_LTLIBRARIES means we will use libtool to create what's called a convenience library called libgtest.la. With subdir-objects enabled, it will be built into the /tests directory, but not installed. This means that, whenever we want to update our tests, we don't have to recompile the Google Test library libgtest.la. This will save time when testing and help us iterate faster. Then, we will want to compile our unit tests against it later as we update them. The library will only be compiled upon running make check, saving time by not compiling it if all we want to do is make or make install.
The Second Problem
Now, the second problem needs to be refined: How do you (a) create a test (b) that is linked to the Google Test libraries and thus uses them? The questions are kind of intertwined, so we answer them at once.
Creating a test is just a matter of putting the following code into a gtest.cpp file located at /tests/gtest.cpp:
#include "gtest/gtest.h" // we will add the path to C preprocessor later
TEST(CategoryTest, SpecificTest)
{
ASSERT_EQ(0, 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
This runs only the simple test 0=0. To create a test for your library, you need to read the primer. You'll notice we don't need a header for this (yet). We are linking to the file "gtest/gtest.h", so we'll need to make sure that we tell automake to include a directory that has gtest/gtest.h.
Next, we need to tell automake that we want to build a test and run it. The test is going to build into an executable that we don't want to install. Then automake is going to run that executable. It will report whether that executable says the tests passed or failed.
Automake does that by looking in the makefile for the variable check_PROGRAMS. These are the programs it will compile, but it won't necessarily run them. So we add to /tests/Makefile.am:
check_PROGRAMS = gtest
gtest_SOURCES = gtest.cpp
gtest_LDADD = libgtest.la
gtest_LDFLAGS = -pthread
gtest_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest -pthread
The gtest_SOURCES finds the /tests/gtest.cpp file and compiles it. gtest_LDADD links against libgtest.la which will be compiled into the /tests directory. Google wants us to use the gtest_LDFLAGS line to enable pthreads. Finally, we need to include the location where the header "gtest/gtest.h" will be found, and that is the gtest_CPPFLAGS line. Google also wants us to include the /googletest/googletest location, and include the
The state of things: The Google Test library libgtest.la will compile with make into the directory /tests, but not be installed. The binary gtest will only be compiled with make check, but will not be installed.
Next we want to tell automake to actually run the compiled binary gtest and report errors. This is accomplished by adding a line to /tests/Makefile.am:
TESTS = gtest
The final /tests/Makefile.am looks like this:
check_LTLIBRARIES = libgtest.la
libgtest_la_SOURCES = ../googletest/googletest/src/gtest-all.cc
libgtest_la_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest -pthread
check_PROGRAMS = gtest demo
gtest_SOURCES = gtest.cpp ../src/fields.cpp
gtest_LDADD = libgtest.la
gtest_LDFLAGS = -pthread
gtest_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/src
demo_SOURCES = demo.cpp ../src/fields.cpp
demo_CPPFLAGS = -I$(top_srcdir)/src
TESTS = gtest
Now, autoreconf -fiv (note any errors and hopefully fix them) from /, and make check and you should get a test that runs:
build(dev)$ make check
Making check in tests
/Applications/Xcode.app/Contents/Developer/usr/bin/make gtest
make[2]: `gtest' is up to date.
/Applications/Xcode.app/Contents/Developer/usr/bin/make check-TESTS
PASS: gtest
============================================================================
Testsuite summary for IonMotion 0.0.1
============================================================================
# TOTAL: 1
# PASS: 1
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
Here is a sample Makefile.am for the unit test project (project name: TestProject). It depends on GTEST and GMOCK:
Makefile.am
#######################################
# The list of executables we are building seperated by spaces
# the 'bin_' indicates that these build products will be installed
# in the $(bindir) directory. For example /usr/bin
#bin_PROGRAMS=exampleProgram
# Because a.out is only a sample program we don't want it to be installed.
# The 'noinst_' prefix indicates that the following targets are not to be
# installed.
noinst_PROGRAMS=utTestProject
#######################################
# Build information for each executable. The variable name is derived
# by use the name of the executable with each non alpha-numeric character is
# replaced by '_'. So a.out becomes a_out and the appropriate suffex added.
# '_SOURCES' for example.
# Sources for the a.out
utTestProject_SOURCES= \
utTestProject.cpp
# Library dependencies
utTestProject_LDADD = \
$(top_srcdir)/../TestProject/build/${host}/libTestProject/.libs/libTestProject.a \
../$(PATH_TO_GTEST)/lib/libgtest.a \
../$(PATH_TO_GMOCK)/lib/libgmock.a
# Compiler options for a.out
utTestProject_CPPFLAGS = \
-std=c++11 \
-I../$(PATH_TO_GTEST)/include \
-I../$(PATH_TO_GMOCK)/include \
-I$(top_srcdir)/include \
-I$(top_srcdir)/..
TESTS = utTestProject
TESTS_ENVIRONMENT = export UT_FOLDER_PATH=$(top_srcdir)/utTestProject; \
export GTEST_OUTPUT="xml";
Compiling gtest:
# Useful vars
SourceVersionedArchiveFolderName="gtest-1.7.0"
#
# Make it
#
pushd .
cd ./${SourceVersionedArchiveFolderName}/make
make gtest.a
if [ $? != 0 ]; then
echo "$0: Make failed"
exit 1
fi
popd
It's worth noting that Googletest doesn't officially maintain its Autotools integration anymore:
Before settling on CMake, we have been providing hand-maintained build
projects/scripts for Visual Studio, Xcode, and Autotools. While we
continue to provide them for convenience, they are not actively
maintained any more. We highly recommend that you follow the
instructions in the above sections to integrate Google Test with your
existing build system.
https://github.com/google/googletest/tree/master/googletest#legacy-build-scripts
It's now recommended to build Googletest with CMake.
Making GoogleTest's source code available to the main build can be
done a few different ways:
Download the GoogleTest source code manually and place it at a known
location. This is the least flexible approach and can make it more
difficult to use with continuous integration systems, etc.
Embed the
GoogleTest source code as a direct copy in the main project's source
tree. This is often the simplest approach, but is also the hardest to
keep up to date. Some organizations may not permit this method.
Add
GoogleTest as a git submodule or equivalent. This may not always be
possible or appropriate. Git submodules, for example, have their own
set of advantages and drawbacks.
Use CMake to download GoogleTest as
part of the build's configure step. This is just a little more
complex, but doesn't have the limitations of the other methods.
https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project

Importing Existing QT C++ Project with its own Makefile in Eclipse

I would like to import an C++ GUI Project with its own Makefile in Eclipse.
In the command prompt, everything works fine. But when I import the project, it gives an error
make all
make: *** No rule to make target `all'. Stop.
Would be glad, if you give me an idea where I am going wrong.
Thanks
Kiran
How did you import the project? I have used Eclipse with existing makefile projects a couple of times by creating a new empty makefile project and overriding the location of the project to refer to where the Makefile is present. It warns that the directory already exists, but it works fine.
Make sure that your Makefile has an "all" target.
A typical all target rule could look like
all: ../bin/myApplicationName
#true
You'll probably also want to include a rule for clean if you don't already have one.
clean:
#-rm -f ../bin/myApplicationName *.o *.d