I want to give examples to some users of my project. The exmaple is to be used CMake. And It's like:
- top level
CMakeLists.txt
-- example A
A.cpp
CMakeLists.txt
-- example B
B.cpp
CMakeLists.txt
-- example C
C.cpp
CMakeLists.txt
I want to set some common CMake options in the top CMakeLists.txt, like:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fexperimental-library")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lc++abi -fuse-ld=lld")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
And I want that the example project can be built one time and the sub example can be built independently.
#A.cpp
cmake_minimum_required(VERSION 3.24)
# Something to be added
project(A)
add_executable(${PROJECT_NAME} A.cpp)
But I wish that I can do it without copy the common options into each CMakeLists.txt. I don't find a simple answer on StackOverflow or throughout Google. I think it should be a question may be met frequently in the fact. It's helpful to provide a tutorial even just a tutorial url.
Simply use add_subdirectory? Would simplify things and should still meet your requirement?
option(MYPROJECT_BUILD_EXAMPLES "Build examples" OFF/ON)
...
if (MYPROJECT_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
I was experimenting with CMake, until i stumped on this error:
CMake Error at CMakeLists.txt:34:
Parse error. Expected "(", got newline with text "
".
-- Configuring incomplete, errors occurred!
I though, ok fine, I'll fix the code at line 34, as suggested:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(msv-auth VERSION 0.1)
# add the executable
add_executable(app "${CMAKE_CURRENT_SOURCE_DIR}/src/app.cpp")
# app name
get_target_property(Z_APP_NAME app NAME)
# specify compiler
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# specify C++ compiler flags
set(CMAKE_CXX_FLAGS -pthread)
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -o\"${CMAKE_CURRENT_SOURCE_DIR}/target/debug/${Z_APP_NAME}\")
else()
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -O3)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -o\"${CMAKE_CURRENT_SOURCE_DIR}/target/release/${Z_APP_NAME}\")
endif()
#includes
target_include_directories(app INTERFACE "/usr/local/include/oatpp-1.3/oatpp")
#libs
target_link_directories(app INTERFACE "/usr/local/oatpp-1.3.0")
target_link_libraries(app oatpp)
But I can't seem able to fix that error even after I tried multiple times. OK, I though, let's simplify things a bit, and make a completely new CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
# set the project name
project(msv-auth VERSION 0.1)
# add the executable
add_executable(app "${CMAKE_CURRENT_SOURCE_DIR}/src/app.cpp")
# specify compiler
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
# specify C++ compiler flags
set(CMAKE_CXX_FLAGS -pthread)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -o\"${CMAKE_CURRENT_SOURCE_DIR}/target/debug/app\")
#includes
target_include_directories(app INTERFACE "/usr/local/include/oatpp-1.3/oatpp")
#libs
target_link_directories(app INTERFACE "/usr/local/oatpp-1.3.0")
target_link_libraries(app oatpp)
(There is only 23 lines of code in the 2nd CMakeLists.txt file)
However, running cmake .., it produced this error:
CMake Error at CMakeLists.txt:34:
Parse error. Expected "(", got newline with text "
".
-- Configuring incomplete, errors occurred!
Exactly the same error on the same exact line number! Like, how can there be an error on line 34 if there's only 23 lines on the file?!
Even creating a new folder, renaming every file, or even running a completely different CMakeLists.txt on a completely different folder for a completely different project, produced the same exact error message. Even rebooting the computer did not fix it at all. I've even tried uninstall and installing CMake again, still the same issue.
Anyone ever stumped on this kind of error? How did you fix it?
You don't call the good CMakeLists.
============================
Sorry to say that but your CMakeLists is ugly and aggregate many bad practices.
It should be as simple as this (you could add install target, but here is a good starter):
cmake_minimum_required(VERSION 3.10)
project(msv-auth
LANGUAGES CXX
VERSION 0.1
)
find_package(oatpp REQUIRED)
find_package(Threads REQUIRED) # are you sure it's a direct dependency?
add_executable(app src/app.cpp)
target_link_libraries(app PRIVATE oatpp::oatpp Threads::Threads)
target_compile_features(app PRIVATE cxx_std_17)
Everything else should be injected externally (through arguments of cmake configuration, toolchain file, CMakePresets): compiler, custom flags, exact C++ standard you want, oatpp local install path in CMAKE_PREFIX_PATH, etc.
OK, I fix it! How? For some reason, all I did was this:
cmake . --fresh
Well, it won't work since my CMake wasn't v3.24 (mine is v3.23) and it did complain saying that was not a known argument. However I retried cmake ., and suddenly it can compile the CMakeLists.txt just fine. I guess this is a bit of a bug on CMake, that for some reason it was stuck on broken CMakeLists.txt from another test project that I did before and somehow did not look at the CMakeLists.txt of my current directory? Or is it some FreeBSD bug? I don't know TBH.
Edit: for context on why my CMake was 3.23: this is the latest version on PKG for FreeBSD. I wasn't thinking of compiling CMake from source yet.
When I try to run a CMake generated makefile to compile my program, I get the error that
range based for loops are not supported in C++ 98 mode.
I tried adding add_definitions(-std=c++0x) to my CMakeLists.txt, but it did not help.
I tried this too:
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=gnu++0x)
endif()
When I do g++ --version, I get:
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
I have also tried SET(CMAKE_CXX_FLAGS "-std=c++0x"), which also does not work.
I do not understand how I can activate C++ 11 features using CMake.
CMake 3.1 introduced the CMAKE_CXX_STANDARD variable that you can use. If you know that you will always have CMake 3.1 or later available, you can just write this in your top-level CMakeLists.txt file, or put it right before any new target is defined:
set (CMAKE_CXX_STANDARD 11)
If you need to support older versions of CMake (quite unlikely these days), here is a macro I came up with that you can use:
macro(use_cxx11)
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
endif ()
else ()
set (CMAKE_CXX_STANDARD 11)
endif ()
endmacro(use_cxx11)
The macro only supports GCC right now, but it should be straight-forward to expand it to other compilers.
Then you could write use_cxx11() at the top of any CMakeLists.txt file that defines a target that uses C++11.
CMake issue #15943 for clang users targeting macOS
If you are using CMake and clang to target macOS there is a bug that can cause the CMAKE_CXX_STANDARD feature to simply not work (not add any compiler flags). Make sure that you do one of the following things:
Use cmake_minimum_required to require CMake 3.0 or later, or
Set policy CMP0025 to NEW with the following code at the top of your CMakeLists.txt file before the project command:
# Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
if (POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif ()
The CMake command target_compile_features() is used to specify the required C++ feature cxx_range_for. CMake will then induce the C++ standard to be used.
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)
There is no need to use add_definitions(-std=c++11) or to modify the CMake variable CMAKE_CXX_FLAGS, because CMake will make sure the C++ compiler is invoked with the appropriate command line flags.
Maybe your C++ program uses other C++ features than cxx_range_for. The CMake global property CMAKE_CXX_KNOWN_FEATURES lists the C++ features you can choose from.
Instead of using target_compile_features() you can also specify the C++ standard explicitly by setting the CMake properties
CXX_STANDARD
and
CXX_STANDARD_REQUIRED for your CMake target.
See also my more detailed answer.
I am using
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
But if you want to play with C++11, g++ 4.6.1 is pretty old.
Try to get a newer g++ version.
The easiest way to set the Cxx standard is:
set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
See the CMake documentation for more details.
On modern CMake (>= 3.1) the best way to set global requirements is:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
It translates to "I want C++11 for all targets, it's not optional, I don’t want to use any GNU or Microsoft extensions."
As of C++17, this still is IMHO the best way.
Source: Enabling C++11 And Later In CMake
As it turns out, SET(CMAKE_CXX_FLAGS "-std=c++0x") does activate many C++11 features. The reason it did not work was that the statement looked like this:
set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
Following this approach, somehow the -std=c++0x flag was overwritten and it did not work. Setting the flags one by one or using a list method is working.
list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
For CMake 3.8 and newer you can use
target_compile_features(target PUBLIC cxx_std_11)
If you want the generation step to fail if the toolchain cannot adhere to this standard, you can make this required.
set_target_properties(target PROPERTIES CXX_STANDARD_REQUIRED ON)
If you want strict adherence to standard C++ i.e. avoid C++ extensions offered by your compiler (like GCC's -std=gnu++17), additionally set
set_target_properties(target PROPERTIES CXX_EXTENSIONS OFF)
This is documented in detail at An Introduction to Modern CMake -> Adding Features -> C++11 and Beyond. It also offers advice on how to achieve this on older versions of CMake if you're constrained to those.
The easiest way:
add_compile_options(-std=c++11)
This is another way of enabling C++11 support,
ADD_DEFINITIONS(
-std=c++11 # Or -std=c++0x
# Other flags
)
I have encountered instances where only this method works and other methods fail. Maybe it has something to do with the latest version of CMake.
Modern cmake offers simpler ways to configure compilers to use a specific version of C++. The only thing anyone needs to do is set the relevant target properties. Among the properties supported by cmake, the ones that are used to determine how to configure compilers to support a specific version of C++ are the following:
CXX_STANDARD sets the C++ standard whose features are requested to build the target. Set this as 11 to target C++11.
CXX_EXTENSIONS, a boolean specifying whether compiler specific extensions are requested. Setting this as Off disables support for any compiler-specific extension.
To demonstrate, here is a minimal working example of a CMakeLists.txt.
cmake_minimum_required(VERSION 3.1)
project(testproject LANGUAGES CXX )
set(testproject_SOURCES
main.c++
)
add_executable(testproject ${testproject_SOURCES})
set_target_properties(testproject
PROPERTIES
CXX_STANDARD 11
CXX_EXTENSIONS off
)
In case you want to always activate the latest C++ standard, here's my extension of David Grayson's answer, in light of the recent (CMake 3.8 and CMake 3.11) additions of values of 17 and 20 for CMAKE_CXX_STANDARD):
IF (CMAKE_VERSION VERSION_LESS "3.8")
SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
SET(CMAKE_CXX_STANDARD 17)
ELSE()
SET(CMAKE_CXX_STANDARD 20)
ENDIF()
# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)
(Use that code in the place of set (CMAKE_CXX_STANDARD 11) in the linked answer.)
What works for me is to set the following line in your CMakeLists.txt:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Setting this command activates the C++11 features for the compiler and after executing the cmake .. command, you should be able to use range based for loops in your code and compile it without any errors.
I think just these two lines are enough.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
The modern way is to specify the minimum required standard to C++11 with:
target_compile_features(foo PUBLIC cxx_std_11)
This way:
CMake can honor default C++ standard of the compiler if it's greater than C++11
You can clearly specify whether C++ standard is required at build time, consume time, or both. This is nice for libraries.
Public compile features are propagated to downstream targets, so it comes for free in those targets even if they don't directly use this feature.
Users can externally set another C++ standard (more recent basically), with CMAKE_CXX_STANDARD, either from command line or CMake presets. If you hardcode CMAKE_CXX_STANDARD in a CMakeLists, nobody can override the C++ standard without editing your CMakeLists, which is not very pleasant.
It requires CMake >= 3.8
You can use the following. This automatically modifies the feature based on your environment.
target_compile_features(your_target INTERFACE cxx_std_20)
For example,
on Gnu/Linux the following adds -std=gnu++20
on Windows with Clang/Ninja it becomes -std=c++20
on Windows with MSVC it becomes /std=c++20
So you support as many as environments possible.
In case you stumble on that same error using cmake as i did.
You need to set
set (CMAKE_CXX_STANDARD 11)
to activate threading because it is only supported from c++11 ++
hope that helps
OS X and Homebrew LLVM related:
Don't forget to call cmake_minimum_required(VERSION 3.3) and project() after it!
Or CMake will insert project() implicitly before line 1, causing trouble with Clang version detection and possibly other sorts of troubles. Here is a related issue.
I'm new to C++ so be gentle with me. (I know how to code but I get complicated with all the build/compile stuff)
I am using Clion with my C++ project and I have difficult to understand how to include external libraries that I download from the Internet.
for example I have downloaded the OpenCV library (and It located on /usr/local/Cellar/opencv , I cant tell why) and all I have to do in my CmakeLists is to add
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(ArucoMarkersCpp ${OpenCV_LIBS})
this is my full CmakeLists right now:
cmake_minimum_required(VERSION 3.17)
project(ArucoMarkersCpp)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES src/main.cpp)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(ArucoMarkersCpp main.cpp)
target_link_libraries(ArucoMarkersCpp ${OpenCV_LIBS})
I want to include to my project the this library. In all the tutorials I have found, all the examples libraries have inside their main folder, an "include folder" and more. but in this library it seems that it doesn't have it.
The library folder that I downloaded from the link:
I want a General way to do it, without rely on Clion or any other IDE. I want to do it with makefile/Cmakelists (I don't really understand the difference)
Where do people usually put their libraries' files and how they import/include it to their project?
Thanks.
This question already has answers here:
Modern way to set compiler flags in cross-platform cmake project
(5 answers)
Closed 4 years ago.
I am trying to learn CMake with a simple project. This is my sample CMakeLists.txt
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
set(PROJECT_NAME "MyLib" CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
project(${PROJECT_NAME})
include(${CMAKE_SOURCE_DIR}/Sources.cmake)
set(SOURCE_FILES ${COMMON_CPP_FILES} ${COMMON_H_FILES})
include_directories(include)
add_compile_options("$<$<CONFIG:Debug>:/EHa /MTd /W3 /w14640>")
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
I tried to create a Visual Studio project based on this file but I cannot figure out how to properly set the compile flags. When I open Visual Studio I can see the flags (/EHa) as part of "Additional Options" but I can still see the default (/EHsc) flags.
Why the default flags are still there and how can I make sure the compiler is really using the flags that I have specified?
You can check what default flags CMake uses by printing CMAKE_CXX_FLAGS and CMAKE_CXX_FLAGS_{RELEASE|DEBUG}.
Setting these variables with something like
set(CMAKE_CXX_FLAGS "")
will not clear them however.
The only way I've found to do what you are saying (clear specific default flags) is something like this for every default flag:
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
Why you cannot clear all the default flags easily and without this syntax is beyond me, however.