CMake: Change C_INCLUDES in flags.make - cmake

I am using Windows 7 and CMake 3.5 with Cross-Compiling. For compiling I use the IAR 78000 C-Compiler V3.34A/W32 (very old). The include files where added over include_directories() to INCLUDE_DIRECTORIES.
The Compiler needs:
C_INCLUDES = -IC:/foo/bar/
But CMake creats in the flags.make file only:
C_INCLUDES = -IC:/foo/bar (without Backslash at the end)
I tried:
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
set(include_dirs)
foreach(it ${cmake_include_directories})
set(include_dirs ${include_dirs} "${it}/")
endforeach()
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "${include_dirs}")
#set_property(TARGET ${PROJECT_NAME}.hex PROPERTY INCLUDE_DIRECTORIES ${include_dirs})
message(STATUS "New Dir: ${include_dirs}")
But the values in include_dir will not override the values in INCLUDE_DIRECTORIES
Is it possible to change my INCLUDE_DIRECTORIES only for the C_INCLUDES, to have the desired format?
Update: The solution for my problem
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
foreach(iterationValue ${cmake_include_directories})
set(iterationValue ${iterationValue}////) # You need //// for one /!
target_include_directories(
${PROJECT_NAME} PRIVATE
${iterationValue}
)
endforeach()
Thank you

Related

Problem using FetchContent_Declare together with shared library

I'm having problem using FetchContent_Declare with a shared library. I'm trying to apply a modular design (instead of creating one mega-repository with 20 modules I'm allocating a dedicated repository to each module). I'm trying to use FetchContent_Declare in order to link dependant modules together (I'm not a fan of git-submodules since those require that user manually initialises them). The problem I'm having is that the DLL generated by the project fetched via the mentioned function isn't copied to the binary output of the parent project. Here is a dependency graph to make it more clear.
Repo A:
- bin
- bin-etc
- lib
- include
- project_a
.. header files ..
- src
- CMakeLists.txt : 1
.. source files ..
- CMakeLists.txt : 2
Repo B: Includes A
- bin
- bin-etc
- lib
- output
.. cmake files are built from here ..
- _deps
- project_a-src
- bin
.. here the DLL file is being generated ..
- include
- project_a
.. header files ..
- src
- CMakeLists.txt : 3
.. source files ..
- CMakeLists.txt : 4
The DLL file is being generated in ./output/_deps/project_a-src/bin instead of ./bin.
Here are my CMakeLists.txt files:
# CMakeLists.txt : 1
cmake_minimum_required(VERSION 3.16)
set(PROJECTNAME project_a)
set(PROJECTDIR "${CMAKE_CURRENT_SOURCE_DIR}")
file(GLOB_RECURSE inc "${CMAKE_CURRENT_SOURCE_DIR}/../include/*.hpp")
file(GLOB_RECURSE src "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" FILES ${inc})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${src})
if (MSVC)
add_compile_options(/W3) # warning level 3
add_compile_options(/MP) # Multi-processor compilation
endif()
add_library(
${PROJECTNAME}
SHARED
${inc}
${src}
)
target_include_directories(${PROJECTNAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include/")
# CMakeLists.txt : 2 and 4
cmake_minimum_required(VERSION 3.16)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_SYSTEM_VERSION 10.0.19041.0)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin-etc")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
project(project_a LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED)
add_subdirectory(src)
# CMakeLists.txt : 3
cmake_minimum_required(VERSION 3.16)
set(PROJECTNAME project_b)
set(PROJECTDIR "${CMAKE_CURRENT_SOURCE_DIR}")
file(GLOB_RECURSE inc "${CMAKE_CURRENT_SOURCE_DIR}/../include/*.hpp")
file(GLOB_RECURSE inc_src "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
file(GLOB_RECURSE src "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" FILES ${inc})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${inc_src})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${src})
if (MSVC)
add_compile_options(/W3) # warning level 3
add_compile_options(/MP) # Multi-processor compilation
endif()
add_library(
${PROJECTNAME}
SHARED
${inc}
${inc_src}
${src}
)
target_include_directories(${PROJECTNAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include/")
include(FetchContent)
FetchContent_Declare(project_a
GIT_REPOSITORY <REPO LINK>
GIT_TAG master)
FetchContent_MakeAvailable(project_a)
target_link_libraries(${PROJECTNAME} project_a)
What would be the solution to this problem? Should I use another approach for the design like this? Is adding a simple copy command to cmake the right solution?
Variables like CMAKE_RUNTIME_OUTPUT_DIRECTORY affects on the output directory for all further created libraries ... unless the variable is changed.
The project_a in CMakeLists.txt(2) does
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
unconditionally, so it changes the variable even if it is built as a subproject (with FetchContent).
Generally, any project in its root CMakeLists.txt could check, whether it is actually top-level project. And perform some settings only in case it is:
cmake_minimum_required(VERSION 3.21)
project(project_a LANGUAGES CXX)
if (PROJECT_IS_TOP_LEVEL)
# Do global settings only if we are top-level project.
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_SYSTEM_VERSION 10.0.19041.0)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin-etc")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
endif()
# Other settings are treated as project-specific,
# so could be done in "subproject mode" too.
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED)
add_subdirectory(src)
Note, that variable PROJECT_IS_TOP_LEVEL appears only in CMake 3.21. For detect, whether the project is top-level in older CMake versions, consult that question and its answers: How to detect if current scope has a parent in CMake?.

What does this CMake error mean? And how could I go about resolving it?

I get this error, which I've been trying to understand for some time now but getting nowhere.
add_library cannot create target "Plugin" because another target
with the same name already exists. The existing target is a shared library created
in source directory "D:/CHAI3D/SOFA/src/applications/plugins/plugin".
See documentation for policy CMP0002 for more details.
Below is the CMakelists.txt added for reference. I tried to remove the unnecessary code. So far, I've tried allowing duplicate targets with set(ALLOW_DUPLICATE_CUSTOM_TARGETS TRUE)
But to no avail
cmake_minimum_required(VERSION 3.1)
project(Plugin VERSION 21.06.99)
# Policies
cmake_policy(SET CMP0079 NEW)
set(ALLOW_DUPLICATE_CUSTOM_TARGETS TRUE)
set (PLUGIN_VERSION ${PROJECT_VERSION})
set(HEADER_FILES
src/initPlugin.h
...
)
set(SOURCE_FILES
src/initPlugin.cpp
...
)
file(GLOB_RECURSE RESOURCE_FILES "*.md" "*.psl" "*.py" "*.pyscn" "*.scn" "*.ah")
add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${RESOURCE_FILES} )
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-DSOFA_BUILD_PLUGIN")
target_link_libraries(${PROJECT_NAME} SofaCore SofaConstraint SofaSimpleFem SofaBaseMechanics SofaRigid SofaBaseVisual SofaOpenglVisual)
## Install rules for the library and headers; CMake package configurations files
sofa_create_package_with_targets(
PACKAGE_NAME ${PROJECT_NAME}
PACKAGE_VERSION ${PROJECT_VERSION}
TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES
INCLUDE_SOURCE_DIR "src"
INCLUDE_INSTALL_DIR ${PROJECT_NAME}
RELOCATABLE "plugins"
)
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER "plugins")

how to used cmake link the pthread and CURSES [duplicate]

I'm running RHEL 5.1 and use gcc.
How I tell cmake to add -pthread to compilation and linking?
#Manuel was part way there. You can add the compiler option as well, like this:
If you have CMake 3.1.0+, this becomes even easier:
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_app PRIVATE Threads::Threads)
If you are using CMake 2.8.12+, you can simplify this to:
find_package(Threads REQUIRED)
if(THREADS_HAVE_PTHREAD_ARG)
target_compile_options(my_app PUBLIC "-pthread")
endif()
if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(my_app "${CMAKE_THREAD_LIBS_INIT}")
endif()
Older CMake versions may require:
find_package(Threads REQUIRED)
if(THREADS_HAVE_PTHREAD_ARG)
set_property(TARGET my_app PROPERTY COMPILE_OPTIONS "-pthread")
set_property(TARGET my_app PROPERTY INTERFACE_COMPILE_OPTIONS "-pthread")
endif()
if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(my_app "${CMAKE_THREAD_LIBS_INIT}")
endif()
If you want to use one of the first two methods with CMake 3.1+, you will need set(THREADS_PREFER_PTHREAD_FLAG ON) there too.
The following should be clean (using find_package) and work (the find module is called FindThreads):
cmake_minimum_required (VERSION 2.6)
find_package (Threads)
add_executable (myapp main.cpp ...)
target_link_libraries (myapp ${CMAKE_THREAD_LIBS_INIT})
Here is the right anwser:
ADD_EXECUTABLE(your_executable ${source_files})
TARGET_LINK_LIBRARIES( your_executable
pthread
)
equivalent to
-lpthread
target_compile_options solution above is wrong, it won't link the library.
Use:
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -pthread")
OR
target_link_libraries(XXX PUBLIC pthread)
OR
set_target_properties(XXX PROPERTIES LINK_LIBRARIES -pthread)

how to use CMake file (GLOB SRCS *. ) with a build directory

this is my current CMakeLists.txt file
cmake_minimum_required(VERSION 3.3)
set(CMAKE_C_FLAGS " -Wall -g ")
project( bmi )
file( GLOB SRCS *.cpp *.h )
add_executable( bmi ${SRCS})
This builds from my source directory, but I have to clean up all the extra files after. My question is how do I build this from a build directory if all my source files are in the same source directory?
thanks
If you really need to use file(GLOB …), this CMakeLists.txt should work :
cmake_minimum_required(VERSION 3.3)
project(bmi)
add_definitions("-Wall" "-g")
include_directories(${PROJECT_SOURCE_DIR})
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
add_executable(bmi ${SRC_FILES})
In this case you have to launch cmake from your build directory every time you add or delete a source file :
cmake <your_source_dir> -G <your_build_generator>
As Phil reminds, CMake documentation doesn't recommend this use of GLOB. But there are some exceptions. You'll get more information on this post.
If you don't meet those exceptions, you'd rather list your source files than use GLOB :
set(SRC_FILES ${PROJECT_SOURCE_DIR}/main.cpp
${PROJECT_SOURCE_DIR}/bmi.cpp
… )
NB : if you have #include of your .h files in .cpp files, I don't see any reason to put them in add_executable, you just need to specify include directory with include_directories.
Cmake used to only update the list of source files if CMakeLists.txt was changed since the last cmake run or if cmake was used to configure the project again.
In cmake 3.11.0 recursive search and automatic re-configuration on adding or deleting source files was added. Since then you can use the following snippet:
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.11.0")
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp *.h)
else()
file(GLOB SOURCE_FILES *.cpp *.h */*.h */*.cpp)
endif()
The file() command after the else() provides at least a bit of backwards compatibility: It still searches for source files in the current folder and its direct subfolders. But it doesn't automatically recognize if there are new files or old files have been deleted.
Note that VERSION_GREATER_EQUAL is only available in cmake >= 3.7

cmake does non link ncurses

I am a total noob concerning cmake. My CMakeLists is really basic:
cmake_minimum_required(VERSION 2.4.6)
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#For the Curses library to load:
SET(CURSES_USE_NCURSES TRUE)
include_directories(
"src/"
)
add_subdirectory(src)
when I make the linker does not find the ncurses commands and in the verbose mode of make I see that the compiler did not add the -lncurses. What do I have to add to the CMakeLists to make it work?
For the super noob, remember target_link_libraries() needs to be below add_executable():
cmake_minimum_required(VERSION 2.8) project(main)
find_package(Curses REQUIRED)
include_directories(${CURSES_INCLUDE_DIR})
add_executable(main main.cpp)
target_link_libraries(main ${CURSES_LIBRARIES})
before use some third party libs, you ought to find it!
in case of ncurses you need to add find_package(Curses REQUIRED) and then use ${CURSES_LIBRARIES} in a call to target_link_libraries() and target_include_directories(... ${CURSES_INCLUDE_DIR}).