autotools: Makefile.am: link if file exists - c++

my Makefile.am creates the executable main: "symplerTest" i want to link the files "geometry/source/*.o". Currently im linking it like this:
symplerTest_LDFLAGS = \
...
geometry/source/*.o
That works. But now in a next step, i want to link only if the files *.o exist. I tried this one:
if ("$(wildcard $(geometry/source/*.o))","")
symplerTest_LDFLAGS += geometry/source/*.o
endif
but get the following error message:
srcUnittest/Makefile.am:81: error: endif without if
srcUnittest/Makefile.am:79: warning: wildcard $(geometry/source/*.o: non-POSIX variable name
srcUnittest/Makefile.am:79: (probably a GNU make extension)
The problem seems to be at ("$(wildcard $(geometry/source/*.o))","")
Thank you!

You are confusing the Automake directive if with the Make
directive ifeq,
The Automake manual at 20 Conditionals
emphasises:
Automake supports a simple type of conditionals.
These conditionals are not the same as conditionals in GNU Make. Automake
conditionals are checked at configure time by the configure script, and affect
the translation from Makefile.in to Makefile. They are based on options passed
to configure and on results that configure has discovered about the host system.
GNU Make conditionals are checked at make time, and are based on variables
passed to the make program or defined in the Makefile.
if is not a Make directive at all. ifeq is a Make directive for which valid
arguments may be of the form (arg1, arg2).
ifeq (arg1, arg2)
means, to Make, if arg1 is equal to arg2.
Arguments of the form (arg1, arg2) are invalid for the Automake directive if.
Valid arguments for the Automake if directive are Automake condition-names,
e.g.
if DEBUG
means, to Automake, if the condition named by DEBUG is true - where
DEBUG is a condition name that you have previously created by means
of the AM_CONDITIONAL
macro.
Refer to the linked documentation.

Related

How to add preprocessor definitions on CMake's command line? [duplicate]

I try to set a preprocessor macro in the command line of CMake. I've tried:
set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project
but it's neither defined when I compile nor can I find the name MY_MACRO in the files generated by CMake at all, except for CMakeCache.txt where it's present in the form:
MY_MACRO:UNINITIALIZED=1
How can I do it?
A good alternative would be to define a cmake option:
OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default
Followed by a condition:
IF(DEFINE_MACRO)
ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)
Then you can turn that option ON/OFF via command line with cmake using the -D flag. Example:
cmake -DDEFINE_MACRO=OFF ..
To make sure the compiler is receiving the definition right, you can call make in verbose mode and check for the macro being defined or not:
make VERBOSE=1
This is a good solution also because make will recompile your code when any of cmake options changes.
Try this: -D CMAKE_CXX_FLAGS=/DMY_MACRO=1
The motivation behind the question was to batch build 3rd party libraries, which is why I wanted to avoid modifying CMakeLists. So years later, even though I don't need that anymore, I figured out that it's easily achievable by means external to CMake:
Invoke CMake as usual, no special flags.
Then:
With MSVC: The compiler reads the CL environment variable to get extra command line arguments. So
set CL=/DMY_MACRO=1 %CL%
then invoke MSBuild to do its job.
With Makefiles: The generated makefiles use the CFLAGS and CXX_FLAGS variables as makefiles are expected to do. So the build can be started by
make CXX_FLAGS=-DMY_MACRO=1
or by setting the corresponding environment variables.
Unless you have a good reason not to, you should use ADD_DEFINITIONS(<name>=<value>[, ...]).
Just add the following line to your CMakeLists.txt:
ADD_DEFINITIONS("MY_MACRO=1")
CMake will take care of the syntax of the switches (be it -D<name>=<value>, or /D<name>=<value>).

Can I manually use CMake's cpp file dependency-scanner in my cmake code?

I am trying to add a custom target with CMake that executes one command for each given .cpp file. The command should only be re-executed when the source file itself or one of the included source files changes. AFAIK to achieve this I need a list of all the included files and add them to the DEPENDS option of the add_custom_command() calls that belong to my custom target.
So is there a built-in way to get that list of included files?
I know about the IMPLICIT_DEPENDS option of the add_custom_command() function but it only works for Makefile generators. I would like to make this work for all generators.
Thank you for your time
Edit:
As requested I will post some cmake code to show what I want to achieve.
I want to add a custom target, that runs clang-tidy on all the given .cpp files. When incrementally building the custom target the clang-tidy commands should be re-run whenever a .cpp file or one of its directly or indirectly included header files is changed. Just like re-runs of the compiler are handled.
# ----------------------------------------------------------------------------------------
# mainTargetName The name of the target that shall be analyzed
# files A list of all the main targets .cpp files
#
function( addStaticAnalysisTarget mainTargetName files )
set(targetName runStaticAnalysis_${mainTargetName})
set(command "clang-tidy-4.0 -checks=* -p ${CMAKE_BINARY_DIR}")
foreach( file ${files} )
get_filename_component( baseName ${file} NAME_WE)
set(stampFile ${CMAKE_CURRENT_BINARY_DIR}/analyze_${baseName}.stamp )
set(fullFile ${CMAKE_CURRENT_SOURCE_DIR}/${file})
set(commandWithFile "${command} ${fullFile}")
separate_arguments_for_platform( commandList ${commandWithFile})
add_custom_command(
OUTPUT ${stampFile}
DEPENDS "${fullFile}"
IMPLICIT_DEPENDS CXX "${fullFile}"
COMMAND ${commandList}
COMMAND cmake -E touch "${stampFile}" # without creating a file as a touch-stone the command will always be re-run.
WORKING_DIRECTORY ${CPPCODEBASE_ROOT_DIR}
COMMENT "${commandWithFile}"
VERBATIM
)
list(APPEND stampFiles ${stampFile})
endforeach()
set_source_files_properties(${stampFiles} PROPERTIES GENERATED TRUE) # make the stamp files known to cmake as generated files.
add_custom_target(
${targetName}
DEPENDS ${stampFiles}
)
endfunction()
The problem with that is, that it does not seem to work. When I change included files clang-tidy is not re-run for the affected files.
I used the "Unix Makefile" generator for this example so it should work at least with make. Any hints why it doesn't?
My hopes where that I could achieve the desired behavior for all generators by somehow getting the file-dependencies at cmake time and then adding them to the ''''DEPENDS'''' list. But the dependency scanning must be done each time the command is run, so it can not be done at cmake time. This means that the scanning must be implemented by cmake which it currently is not.
A guy with similar problems:
https://gitlab.kitware.com/cmake/cmake/issues/16830
Edit 2:
I think the problem that the IMPLICIT_DEPENDS option was not working was because I did not use correct filenames. I changed that in the code snipped, but I have not yet tested if it works in the project.
I think the answer to my question is ...
No, you can not use cmakes dependency scanner in the cmake code.
That makes sense, because this problem can not be solved at cmake time, because the dependencies of a .cpp file may change without cmake being re-run.
The problem must be solved within cmake itself at make time. This is done when using the IMPLICIT_DEPENDS option.
Also, I tried to solve a Problem that I did not really have, because at this point I can only run clang-tidy on linux anyways. However, clang-tidy may become available on windows as well and then I may have the problem again.
To sum the comments up:
Tambre stated that CMake is not a compiler and therefore can not do that.
I think this is wrong. According to this article, CMake can parse cpp include dependencies because make has no such dependency searcher itself. That was news to me, but I mostly live on Windows so I am not that familiar with make. It could also be possible that in the meantime make was extended to do its own dependency searching. Also this explains why the IMPLICIT_DEPENDS option is only available for make.
Florian pointed out that it is not necessary to create an own custom target for running clang-tidy. Instead, one can use the CXX_CLANG_TIDY target property to run clang-tidy for each file after compiling it. This means however, that static-analysis can not be separated from the build which could lead to inacceptable buildtimes.
There is the cmake -E cmake_depends command line, that could be used to retrieve dependencies at cmake time. But as stated above, I erroneously thought that I needed the dependencies at cmake time, while I needed them at runtime.
The IMPLICIT_DEPENDS options did not work because I had an error in my cmake code.

Pass output of command line utility to compiler/linker

I want to pass result of the getconf PAGESIZE command output as preprocessor define to my program in form of -DPAGESIZE=`getconf PAGESIZE` for [[gnu::assume_aligned(PAGESIZE)]] in custom allocator declaration.
I tried the following:
add_definitions(-DPAGESIZE=`getconf PAGESIZE`)
But it expanded exactly as -DPAGESIZE="\`getconf" ... PAGESIZE`, where ... is contents of other CMAKE_CXX_FLAGS*. I.e. there is an issue with escaping of backticks in CMakeLists.txt files.
How to properly pass such an arguments to compiler/linker in CMakeLists.txt files? Maybe is there another way to achieve desired?
Also I tried add_definitions(-DPAGESIZE="$$(getconf PAGESIZE)") ($$ expanded as $ by cmake), but -DPAGESIZE and the rest part are splitted by cmake. add_definitions("-DPAGESIZE=$$(getconf PAGESIZE)") makes cmake to escape every dollar sign though.
According to documentation for add_definitions command, preprocessor definitions, passed to this command, are appended to COMPILE_DEFINITIONS property:
Flags beginning in -D or /D that look like preprocessor definitions are automatically added to the COMPILE_DEFINITIONS directory property for the current directory.
And content of COMPILE_DEFINITIONS property, according to its documentation is always escaped by CMake, so you cannot preserve special meaning of backticks in the build command:
CMake will automatically escape the value correctly for the native build system
Your may modify CMAKE_CXX_FLAGS manually, as you show in your comment.
The better way is to use execute_process command for run needed command at configuration stage, and use its output for add_definitions command. (Or use this output for create additional header file with configure_file).

Disabling cxx support for libtool after calling AC_PROG_CXX

For my project (library), I use configure with libtool and automake to build under linux hosts. The library consists of a C API, as well as an optional C++ extension. So, since
AC_PROG_CXX must be called globally, I use automake conditionals:
*configure.ac*:
AC_PROG_CC
AC_PROG_CXX
AM_PROG_AR
LT_INIT
... some tests to figure out 'build_cxx' ...
AC_CONDITIONAL([CXX], [ test x$build_cxx = xyes ])
And inside Makefile.am
sources = files.c
if CXX then
cxx_sources = files.cpp
else
cxx_sources =
endif
sources = $sources $cxx_sources
The whole thing, however, does not work when configure is not able to locate g++ (which practically kills the extra logic for the c++ extension). After some research, I've come down to the conclusion that AC_PROG_CXX somehow tells libtool to assume that c++ support. I was also surprised to realise that if AC_PROG_CXX fails, it sets CXX to 'g++'!!!
Anyway, calling AC_PROG_CXX conditionally produces errors like 'am_fastdepCXX is never defined', which seems logical to me. The worst thing is that the error is not shown while configure is running, but it appears later in the linking phase, in to form of 'unknown libtool option -o' (ouch).
The full source code can be found here -> http://bitbucket.org/sdlu/sdlu/src
Can somebody help me?
Thanks in advance...
It's an Automake limitation, it doesn't care about the condition when choosing the linker.
One work-around is to conditionally rewrite the _LINK command, as suggested in this mailing list post:
if USE_CXX
cxx_sources = ...
else
cxx_sources =
libSDLU_la_LINK = $(LINK) $(libSDLU_la_CFLAGS) $(libSDLU_la_LDFLAGS)
endif
Another way (suggested in the same discussion) is to put the C++ sources in a utility library that is built and added conditionally, then added to the main library:
if CXX
noinst_LTLIBRARIES = libSDLUxx.la
libSDLUxx_la_SOURCES = src/cxx/SDLU_CButton.cxx \
src/cxx/SDLU_CIniHandler.cxx \
src/cxx/SDLU_CRenderer.cxx \
src/cxx/SDLU_CSprite.cxx \
src/cxx/SDLU_CTexture.cxx \
src/cxx/SDLU_CWindow.cxx
libSDLU_la_LIBADD = libSDLUxx.la
endif
Some unrelated notes
Do not put generated files (Makefile.in, configure, etc) into source control.
Add a bootstrap script that invokes the autotools to generate things.
Prefer pkg-config (i.e. PKG_CHECK_MODULES(SDL2, sdl2)) over hand-crafted autoconf macros (i.e. AM_PATH_SDL2);
Do not install autoheaders (i.e. SDLU_config.h.in). It makes your library incompatible with every autoconf-based software, as you are re-defining PACKAGE, VERSION, and all library-detection macros. See my answer in this question for examples on how to do it.
I would have the C++ API built and installed as an independent, optional library; drop the sdlu-config script altogether, then write sdluxx.pc that requires sdlu. Do not bother checking if the C++ compiler works, if the user passed --enable-cxx he knows what he's doing; I prefer to have the build fail than silently have an incomplete library.
I don't think it is a good idea to interfere in the handling of the CXX variable.
Use your own variable BUILD_CXX
AC_CONDITIONAL([BUILD_CXX], [ test x$build_cxx = xyes ])here
and
if BUILD_CXX
# ....
endif

Suppress "C source seen but `CC` undefined" in automake?

I have a Makefile.am for compiling Ocaml source code with ocamlbuild. However, even
though I have
AM_INIT_AUTOMAKE([foreign no-dependencies])
in my configure.ac, automake thinks that a C compiler must be present to install exectuables. That is, if I put in Makefile.am a target executable under bin_PROGRAMS that is to be built with ocamlbuild, autoreconf (version 1.11.3) tells me:
Makefile.am: C source seen but `CC' is undefined
Makefile.am: The usual way to define `CC' is to add `AC_PROG_CC'
Makefile.am: to `configure.ac' and run `autoconf' again.
autoreconf: automake failed with exit status: 1
I do not want to include AC_PROG_CC because my source code includes no C. It is pure Ocaml. What can I do? (I have the same problem with libexec_PROGRAMS.)
It may be unneeded, but will it hurt anything to simply add AC_PROG_CC to Makefile.am? Path of least resistance and all.
Working off this decade-old mailing list message:
http://lists.gnu.org/archive/html/automake/2003-01/msg00057.html
It sounds like you might need to define progname_SOURCES as empty. If I understand the post correctly, if you omit an explicit declaraction, progname_SOURCES will implicitly be defined as progname.c.
If you add AC_SUBST([CC]) to configure.ac, that will be enough to define the variable as far as Automake is concerned.