pass variable value to make using cmake - c++

I'm trying to do something like
cmake -DUSE_FILES_FOR_INPUT=ON ..
and then get make to compile my files with -DUSE_FILES_FOR_INPUT=ON. But I don't get the =ON value. It seems that it should be written to a flags.make file, but it isn't:
$ grep USE_FILES_FOR_INPUT source/CMakeFiles/myprogram.dir/flags.make
CXX_DEFINES = -DUSE_FILES_FOR_INPUT
If I manually change that file with -DUSE_FILES_FOR_INPUT=ON then everything works fine.
How can I get cmake to add the value in flags.make?
A different approach to what I need to do: the variable I am using has type BOOL, so it would be good enough to get
CXX_DEFINES = -DUSE_FILES_FOR_INPUT when I do cmake -DUSE_FILES_FOR_INPUT=ON ..
and
CXX_DEFINES = when I do cmake -DUSE_FILES_FOR_INPUT=OFF ..
Is this possible?

Here is a small demonstration,
// demo.cpp
#include <iostream>
using namespace std;
int main()
{
#ifdef USE_FILES_FOR_INPUT
cout << "Using files.." << endl;
#else
cout << "Not using files.." << endl;
#endif
return 0;
}
The CMakeLists.txt,
cmake_minimum_required(VERSION 3.0)
add_executable(demo demo.cpp)
if (USE_FILES_FOR_INPUT)
add_definitions(-DUSE_FILES_FOR_INPUT)
endif()
And a sample output,
baris$ cmake . && make && ./demo
<...>
Not using files..
baris$ cmake -DUSE_FILES_FOR_INPUT=ON . && make && ./demo
<...>
Using files..

You should look at the configure_file documentation. They show an example using the special cmake construct #cmakedefine. This may be a little more work than Baris describes, but I prefer using configure_file and #cmakedefine to get cmake settings into C++ code.
Here is the complete example:
Consider a source tree containing a foo.h.in file:
#cmakedefine FOO_ENABLE
#cmakedefine FOO_STRING "#FOO_STRING#"
An adjacent CMakeLists.txt may use configure_file to configure the header:
option(FOO_ENABLE "Enable Foo" ON)
if(FOO_ENABLE)
set(FOO_STRING "foo")
endif()
configure_file(foo.h.in foo.h #ONLY)
This creates a foo.h in the build directory corresponding to this source directory. If the FOO_ENABLE option is on, the configured file will contain:
#define FOO_ENABLE
#define FOO_STRING "foo"
Otherwise it will contain:
/* #undef FOO_ENABLE */
/* #undef FOO_STRING */
One may then use the include_directories() command to specify the output directory as an include directory:
include_directories(${CMAKE_CURRENT_BINARY_DIR})
so that sources may include the header as #include <foo.h>.

Related

Meson creates build files which will not compile

I am trying to port an existing code tree to the meson build system on a centos 7 machine. Meson configure works fine, but when I try to compile, it fails. The code is proprietary, so I have created an example that illustrates the problem (accurately enough, I hope.) I am not at liberty to restructure the directory tree.
Here's the tree:
mesonex/
alpha/
beta/
alpha/
inc/
funcs.h
numbers.h
src/
numbers.cpp
funcs.cpp
src/
example.cpp
meson.build
My meson.build:
project('example', 'cpp')
srcs=['example.cpp']
srcs+='../beta/alpha/src/funcs.cpp'
srcs+='../beta/alpha/src/funcs.cpp'
incdirs=include_directories('../beta/alpha/inc')
executable('example', srcs, include_directories: incdirs)
here is the main example.cpp file:
#include <iostream>
#include "../beta/alpha/inc/numbers.h"
#include "../beta/alpha/inc/funcs.h"
int main()
{
std::cout << "Hello" << std::endl;
std::cout << interestingNumber() << std::endl;
std::cout << interestingFunc() << std::endl;
}
These are the supporting cpp files:
// funcs.cpp
#include "../inc/numbers.h"
float interestingFunc()
{
return (interestingNumber()+1)/2;
}
// numbers.cpp
float interestingNumber()
{
return 11.3355;
}
And these are the header files:
// funcs.h
float interestingFunc();
// numbers.h
float interestingNumber();
Please note that the duplication in directory names is intentional. Maybe this confuses meson in figuring out how to handle the #includes?
This is just one example of many different build strategies I have tried.
I see right off the bat an issue that might just be an issue with your example, and not with your actual code: Meson considers the meson.build file with the project() call to be the "root" of the source directory structure. You cannot ask it to include files outside of the root. It would be about like cp /../foo . on a Unix-like OS. This may just be a mistake in your example, since this isn't the real code of course.
So, if we rewrite this as (mesonex/alpha/meson.build):
# no project(), that would be in mesonex/meson.build)
sources = files(
'example.cpp',
'../beta/alpha/src/funcs.cpp',
'../beta/alpha/src/numbers.cpp', # you have a typo in your example, funcs.cpp is listed twice.
)
executable(
'example',
sources,
include_directories : include_directories('../beta/alpha/inc'),
)
Should work.
Note, that you might want to consider using a convenience static library instead of reaching back to the code, as this is best practice, you could write something like (mesonex/alpha/beta/meson.build):
lib_beta = static_library(
'beta',
['src/funcs.cpp', 'src/numbers.cpp']
)
idep_beta = declare_dependency(
link_with : lib_beta,
include_directories : include_directories('.'),
)
and then in (src/meson.build):
executable(
'example',
'source.cpp',
dependencies : idep_beta
)
is all you need, as the idep_beta carries both the linkage and the include information.
This is a follow on - the solution worked for my example but not for the actual code. My model must have been incomplete (in a way I haven't determined yet.) The configuration stage works, but in the compile stage the #includes in the cpp source are flagged with a "File or directory does not exist." How does meson reconcile the specified include directories with #include statements in the source? The #include paths may be relative to the actual directory of the actual cpp source. Does this mean I have to edit all the #includes in all the sources - that would be a real negative. We work with some VERY large code bases.

Using CMake targets in Visual Studio projects

I am pretty comfortable with CMake when used in Linux. That is, I use CMake to logically group my code into "targets" and abstract such things as "include directories" and other dependencies. Say, inside a large project my modus operandi would be to add_library(..SHARED) for a bunch of related files that provide one logically coherent unit, and target_link_libraries(...) to it from somewhere else.
(Of course, idiosyncrasies of CMake is another topic. I won't digress to discussions about e.g. its syntax.)
Now, for Windows 10. I fired up Visual Studio 2019 Community with the MSVC toolchain (that is, not WSL/WSL2), and created a CMake Project using VS's "New Project" wizard.
It has created for me some boilerplate code, and the whole project tree looks as below:
In this image, EnRouteGeneratedLibrary is something I added as the next step. Inside it, I have one *.hpp file:
#pragma once
template<typename T>
class __declspec(dllexport) SampleTemplateKlass {
public:
T sum(T x, T y) { return x + y; }
};
template class __declspec(dllexport) SampleTemplateKlass<int>;
and the CMakeLists.txt's contents are as follows:
add_library(${TRG} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/SampleTemplateKlass.hpp)
# set_target_sources(${TRG} PUBLIC SampleTemplateKlass.hpp)
set_target_properties(${TRG} PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(${TRG} PUBLIC .)
set(WINDOWS_EXPORT_ALL_SYMBOLS 1)
Finally, in when building a simple "Hello World" executable, I have the following:
//
#include "SampleProjectWithDll.h"
#include "SampleTemplateKlass.hpp"
using namespace std;
int main()
{
cout << "Hello CMake." << endl;
SampleTemplateKlass<int> tmp;
std::cout << tmp.sum(42, 314) << std::endl;
return 0;
}
(This is the boilerplate code created by VS + my additions).
I link as follows:
# CMakeList.txt : CMake project for SampleProjectWithDll, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
add_subdirectory(EnRouteGeneratedLibrary)
# Add source to this project's executable.
add_executable (SampleProjectWithDll "SampleProjectWithDll.cpp" "SampleProjectWithDll.h")
target_link_libraries(SampleProjectWithDll PUBLIC SampleLibrary)
# TODO: Add tests and install targets if needed.
When building all this, I get two errors,
LNK2001 unresolved external symbol _DllMainCRTStartup and LNK1120 1 unresolved externalswith SampleLibrary.dll in the "File" field of the error panel.
The question is, how to make this simple "Hello World" compile and execute under Windows,
using the CMake infrastructure?

CLion does not pick up (complex) pre-processor definitions

EDIT: Turns out the problem was the complexity of my project. Using the simple example below works as expected, but CLion cannot make sense of the complex dependencies of the project I'm working on. Using the linked question as a workaround for now.
I'm using CLion as my C++ IDE and I've added a simple pre-processor directive as a CMake option:
cmake_minimum_required(VERSION 3.10)
project(cmake_macro_test)
set(CMAKE_CXX_STANDARD 14)
option(SIMPLE_FLAG "My simple flag." ON)
if(SIMPLE_FLAG)
add_definitions(-DSIMPLE_FLAG) # Using CMake 3.10
endif()
add_executable(cmake_macro_test main.cpp)
Then my code has conditional compilation sections of the form:
#include <iostream>
int main() {
#ifdef SIMPLE_FLAG
// Do things
std::cout << "Hello, World!" << std::endl;
#else
// Do other things
std::cout << "Goodbye, World!" << std::endl;
#endif
return 0;
}
The flag is set to on by default, so I expected Clion would pick it up from the CMakeLists.txt and highlight the relevant parts of the code.
However, Clion views the //Do things part of the code as dead, and does provide syntax highlighting or auto-complete for that section, unless I actually re-define the flag in the same file which would defeat the purpose of the CMake option.
Is this a known issue with CLion? Is there some way to guarantee that pre-processor flags get picked up by the IDE?

CLion doesn't resolve headers from external library

Some time ago I started a big header library in C++1x using XCode. The current layout of the library is () something like (partial output from ls -R sponf)
sponf/sponf:
ancestors sponf.h sponf_utilities.h
categories sponf_children.h utilities
children sponf_macros.h
sponf/sponf/ancestors:
function.h meter.h set.h simulation.h
sponf/sponf/categories:
free_space.h prng.h random_distribution.h series.h
sponf/sponf/children:
distributions histogram.h random simulations
meters numeric series spaces
sponf/sponf/children/distributions:
arcsine_der.h exponential.h
box_muller.h uniform.h
sponf/sponf/children/meters:
accumulator.h timer.h
#... other subdirs of 'children' ...
sponf/sponf/utilities:
common_math.h limits.h string_const.h
#... other directories ...
I wanted to port this project to CLion, which seems a really good IDE (based on the similar AndroidStudio IDE) but I'm getting some troubles.
Small test program
I tried this small program as a test:
#include <iostream>
#include <sponf/sponf.h>
using namespace std;
int main() {
using space = sponf::spaces::euclidean_free_space<double, 3>;
sponf::simulations::random_walk<space> rw;
rw.step(1);
std::cout << rw.position.value << std::endl;
return 0;
}
The program compiles and runs fine. However, CLion does not recognize the spaces namespace (declared in one of the children files), nor the simulations namespace; they are both marked red and I cannot inspect their content, nor navigate to their definitions by ⌘-clicking, etc. etc...
Relevant parts of the library
Looking in "sponf.h" we find
#ifndef sponf_h
#define sponf_h
/* The classes below are exported */
#pragma GCC visibility push(default)
// include some of the standard library files
// ...
#include <Eigen/Eigen>
#include "sponf_macros.h"
#include "sponf_utilities.h"
#include "sponf_children.h"
#pragma GCC visibility pop
#endif
while in "sponf_children.h" (which is located at the top level, next to "sponf.h") we find
#ifndef sponf_locp_sponf_children_h
#define sponf_locp_sponf_children_h
namespace sponf {
// include some of the children
// ...
#include "children/spaces/euclidean_free_space.h"
#include "children/simulations/random_walk.h"
// include remaining children
// ...
}
#endif
Each "child" header will then include its corresponding "ancestor" or "category" header (which defines the superclass of the "child" itself).
The reaction of CLion
Despite the autocompletition prediction, which easily finds all the subdirectories and the headers, all the include directives in this last file get marked red and ⌘-clicking on any of them leads to a popup message
Cannot find declaration to go to
while the right ribbon of the editor signal many errors like
',' or ) expected
) expected
Declarator expected
Expecting type
Missing ;
Unexpected symbol
which are not the same for each include statement (each generates from 2 to all of these errors).
On the other hand, CLion is perfectly able to find all Eigen headers, which have pretty much the same structure!
I have put both libs in /opt/local/include and changed CMakeLists.txt accordingly
cmake_minimum_required(VERSION 2.8.4)
project(sponf)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(/opt/local/include/sponf /opt/local/include/eigen3)
set(SOURCE_FILES main.cpp)
add_executable(sponf ${SOURCE_FILES})
Why can't CLion properly parse the project structure? XCode, after having included /opt/local/include/sponf and /opt/local/include/eigen3 in the HEADER_SEARCH_PATHS env. variable of the project, is able to find any header while compiling the same exact program.
Is there anything else I need to know? Am I doing it wrong or is it that CLion isn't that mature yet and this is just a sorry bug? This is my first approach to the CLion and the CMake toolchain, so any kind of information about it will be greatly appreciated!
Sorry for the very long question, I didn't manage to shrink it further... Thanks in advance guys, see you soon!
Here what I did in windows using cigwin64. I wanted to use Eigen library include in my project.
Eigen library is places in /usr/include/eigen then edited CMakeLists.txt and add
include_directories("/usr/include/eigen")
into it. Now CLion can find all source files in eigen lib. May be this what you wanted too.
Downgrade to Clion 2016.1.4 fixes the problem

Running unit tests during build of Windows DLL with CMake

I have a C++ library that is built with cmake. The library is tested by unit tests which I would like to run as part of the build. I want the tests to run when the library or unit test source changes.
I found some help in past posts on the cmake mailing list:
http://www.cmake.org/pipermail/cmake/2010-January/034419.html
This approach, using add_custom_command() on the unit test program, works on Linux when the library is shared or static and on Windows when the libary is static. The problem is building the library shared on Windows. In that case, the test runs in the initial build, but doesn't run when the library changes.
Here is an example that illustrates the problem:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(xyz)
SET(BUILD_SHARED_LIBS ON)
#----------- build library
if(${BUILD_SHARED_LIBS})
add_definitions(-DXYZ_SHARED)
endif(${BUILD_SHARED_LIBS})
add_library(${PROJECT_NAME} xyz.cpp xyz.h)
#----------- build unit tests program
add_executable(${PROJECT_NAME}_unit_tests unit_tests.cpp)
target_link_libraries(${PROJECT_NAME}_unit_tests ${PROJECT_NAME})
#----------- run unit tests program after it is built
add_custom_command(TARGET ${PROJECT_NAME}_unit_tests
POST_BUILD COMMAND ${PROJECT_NAME}_unit_tests)
xyz.h
#pragma once
#ifdef XYZ_SHARED
#ifdef _WIN32
#ifdef xyz_EXPORTS
#define XYZ_EXPORT __declspec(dllexport)
#else
#define XYZ_EXPORT __declspec(dllimport)
#endif
#else //_WIN32
#define XYZ_EXPORT
#endif //_WIN32
#else //XYZ_SHARED
#define XYZ_EXPORT
#endif //XYZ_SHARED
XYZ_EXPORT bool xyz_return_true();
xyz.cpp
#include "xyz.h"
XYZ_EXPORT bool xyz_return_true()
{
return true;
}
unit_tests.cpp
#include <iostream>
#include "xyz.h"
int main(int argc, char *argv[])
{
using namespace std;
cout << "running unit tests: ";
if (xyz_return_true()) {
//no error
cout << "pass" << endl;
return 0;
}
//error
cout << "fail" << endl;
return 1;
}
If I build on Windows, then change xyz.cpp's function to return false and build again, the tests aren't run. What can I do to make the tests run in this case?
I think the tests aren't being run because at build time xyz_unit_tests.exe only depends on the import library (xyz.lib). The import library doesn't change if the library interface doesn't change.
I'm using Visual Studio 10 and cmake 2.8.11.2.
You could trigger a test rebuild by deleting the test executable as a post-build event of the library. So, for example:
if(WIN32 AND BUILD_SHARED_LIBS)
#----------- trigger rebuild of tests if lib has changed
get_target_property(TestPath ${PROJECT_NAME}_unit_tests LOCATION)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove ${TestPath}
COMMENT "Removing ${TestPath}")
endif()
You have to use the LOCATION target property rather than a generator expression in the COMMAND argument since that doesn't introduce a cyclic dependency in CMake's dependency graph. Ideally, we'd have the COMMAND argument as:
COMMAND ${CMAKE_COMMAND} -E remove $<TARGET_FILE:${PROJECT_NAME}_unit_tests>
but this would cause the library to depend on the executable, and clearly the target_link_libraries call causes the exe to depend on the lib.
There's probably a better way to make the test executable go out-of-date rather than just deleting it; it seems a bit brute-force to me. But it should work.