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?
Related
Is there a modern approach to use target architecture within a condition for a generator expression in CMake? There are some answers that are somewhat outdated. I am looking for a modern or at least very robust and reliable custom script for using target architecture within a generator expression.
The docs do not seem to contain that kind of info.
One of the ideas for a workaround I see is to use $<<STRING:MY_DETECTED_ARCH:ARCH_ARM>:src_for_arm.cpp>
I checked a solution from this answer and it worked.
cmake_minimum_required(VERSION 3.14.2 FATAL_ERROR)
project(cmake_target_arch)
set(CMAKE_CXX_STANDARD 17)
include(TargetArch.cmake)
target_architecture(TARGET_ARCH)
message(STATUS "target_architecture: ${TARGET_ARCH}")
add_executable(cmake_target_arch
main.cpp
$<$<STREQUAL:"${TARGET_ARCH}","x86_64">:x86_64.cpp>
$<$<STREQUAL:"${TARGET_ARCH}","i386">:i386.cpp>
$<$<STREQUAL:"${TARGET_ARCH}","armv7">:armv7.cpp>
)
main.cpp
#include <iostream>
#include <string>
extern std::string hello_message();
int main()
{
std::cout << hello_message() << std::endl;
return 0;
}
i386.cpp
#include <string>
std::string hello_message()
{
return "Hello i386!";
}
Example output for i386 binary:
C:\Users\serge\dev\repos\cmake_target_arch\cmake-build-release-visual-studio-win32\cmake_target_arch.exe
Hello i386!
I guess one can come up with a CMake Macro to wrap strings comparison
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?
I am new to c++, please don't grill too much. I am trying to use spdlog in C++ program and using CLion from Jetbrains.
Here is my screenshot but don't know what I am doing wrong. Please advise what I am doing wrong .
This is my main.cpp
#include <iostream>
#include "include/spdlog/spdlog.h"
int main() {
std::cout << "Hello, World!" << std::endl;
spdlog::info("hello world");
return 0;
}
This my CMakeList.txt
cmake_minimum_required(VERSION 3.17) project(Lesson01)
set(CMAKE_CXX_STANDARD 14)
add_executable(Lesson01 main.cpp) include_directories(spdlog)
Thanks
In the prototype you have created you have mentioned twice the keyword include
First after the # and a second one in between the quotation mark.
I have been looking in internet and basic writting of spdlog prototype is just. Here the link: https://github.com/gabime/spdlog
#include "spdlog/spdlog.h"
Test is without the second include in your code.
All the best
Mathieu
In your code you have #include "include/spdlog/spdlog.h", and going by the screenshot you linked, this include is found. However it is then complaining that spdlog.h tries to #include <spdlog/common.h>, and this file is not found.
Together this sounds like you are not setting the right include directory for the library, and just getting the first file right by over-specifying the path.
I would try to change include_directories(spdlog) to include_directories(include) (or possibly include_directories(include/spdlog), not entirely sure which folder is the base one with the library in). If you want, then you can also add all of those; I don't think anything will break from adding too many here, but it may impact compile speed so try to only keep the correct one.
Also, after making this change you may need to change your original include from #include "include/spdlog/spdlog.h" to #include "spdlog/spdlog.h".
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
I have a problem with _DEBUG macro on Linux C++.
I tried to use something like this:
#ifdef _DEBUG
cout << "Debug!" << endl;
#endif
But it doesn't work when I select Debug in IDE. However it worked on Windows.
I use Eclipse IDE for C++ coding on Linux.
On windows you were probably using Visual Studio, which automatically defines the _DEBUG symbol when building the solution in Debug mode. Symbols are usually defined when invoking the compiler, and then they will be used during the pre-processor phase.
For example, if you are using GCC via command line and you want to re-use the _DEBUG symbol because you are handling an already established codebase, you can define it using the -D parameter via command line.
#include <iostream>
int main() {
std::cout << "Hello world!\n";
#ifdef _DEBUG
std::cout << "But also Hello Stack Overflow!\n";
#endif
return 0;
}
Compiling this with the following command line
g++ -D _DEBUG define.cpp
will give the following result
Hello world!
But also Hello Stack Overflow!
Your best bet for eclipse cdt however could be to modify the paths and symbols properties in the project properties.
If you use cmake put the following in your your top-level CMakeLists.txt file
set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG "_DEBUG")
found on CMake Mailinglist
Put #define _DEBUG somewhere north of where you have this snippet, or in your project settings.