In my header-only library I have the following CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.11)
project(Math)
set(PROJECT_VERSION 0.1)
# Install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
message("++ Installation prefix set to \"${CMAKE_INSTALL_PREFIX}\"")
configure_file("${CMAKE_SOURCE_DIR}/pkg-config.pc.cmake"
"${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_PREFIX}/include/Math")
install(FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pkgconfig/")
It works normally, but it appears that when I say make clean (which I expect to be a no-op, but for which make should return 0), I get
make[1]: *** No rule to make target `clean'. Stop.
make: *** [clean] Error 2
I see that there does exist a clean target in Makefile in the build dir, but it calls for a clean target in CMakeFiles/Makefile2, where it doesn't exist.
I've found that the target is created if I add the following to CMakeLists.txt:
add_custom_target(clean)
But then I get some annoying warnings for any make invocation:
Makefile:150: warning: overriding commands for target `clean'
Makefile:123: warning: ignoring old commands for target `clean'
I.e. for some reason the Makefile gets two instances of clean target.
How can I create a no-op clean target cleanly, not getting any warnings?
Adding
add_custom_target(dummy_target)
works for me: make clean doesn't issue any error.
Because ALL is not used for custom target, it doesn't appear during make invocation.
Related
I want to build a package that contains a list of files (configuration files that my main task uses). So I am adding these in my CMakeLists.txt
add_custom_target(my-configs)
install(
FILES
file1.cfg
DESTINATION data/task
COMPONENT my-configs
EXCLUDE_FROM_ALL)
...
But when I run :
make -C ../cmake-build/linux_64_static_make_RelWithDebInfo/task/ my-configs
I get :
make: Entering directory '/development/cmake-build/linux_64_static_make_RelWithDebInfo/task'
make: *** No rule to make target 'my-configs'. Stop.
Why is that? Shouldn't the above create the target?
EDIT
This component doesn't do anything apart from copying files into the specified location. In that case, do I need a custom_target at all?
Or could I just go ahead and do cmake install? If I do install I see :
cd ../cmake-build/linux_64_static_make_RelWithDebInfo && DESTDIR=../../cmake-install/linux_64_static_make_RelWithDebInfo cmake -DCOMPONENT=my_configs -P cmake_install.cmake
-- Install configuration: "RelWithDebInfo"
-- Install component: "my_configs"
but nothing gets installed in the DESTDIR as expected - which is why I thought I needed a target so I can regenerate the cmake-build tree? Otherwise how will it know about the new component?
One use case for add_custom_target() can be like a .PHONY target in a Makefile.
You need to add dependencies to your custom target so that CMake knows how to fill the order. Here some examples:
add_custom_target(libs DEPENDS library_1 library_2 ...)
So now you have a target libs that will build your set of libraries when you specify that target to be built or some other target depends on libs to be built.
Another example:
add_custom_target(unmount_server COMMAND "umount /mnt/deployment")
This would provide a target that would unmount a server drive. Very much a non-portable operation as I have written it.
I am new to CMake. I can not resolve the flowing error. Could someone help me?
------------ERROR--------------
ld: library not found for -lnetcdf
collect2: error: ld returned 1 exit status
make[3]: *** [NUP] Error 1
make[2]: *** [CMakeFiles/NUP.dir/all] Error 2
make[1]: *** [CMakeFiles/NUP.dir/rule] Error 2
make: *** [NUP] Error 2
------------------- CMake File------------------
cmake_minimum_required(VERSION 3.10.0)
project(NUP Fortran)
enable_language(Fortran)
set(INCLUDE_FILE /usr/local/Cellar/netcdf/4.7.4/include)
set(lib_FILE /usr/local/Cellar/netcdf/4.7.4/lib)
find_package(netcdf REQUIRED)
if(netcdf_FOUND)
include_directories(${INCLUDE_FILE})
set(
SOURCE_FILES
${PROJECT_BINARY_DIR} unpack.f90
)
add_executable(NUP ${SOURCE_FILES} )
target_link_libraries(NUP netcdf)
endif()
--------------unpack.f90-------------------
PROGRAM unpack_array
IMPLICIT NONE
INCLUDE 'netcdf.inc'
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(12,307)
......
I am using MACOS Catalina. Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
If you're using find_package() to find NetCDF on your machine, you shouldn't need to manually specify the paths as you have. Let find_package do that for you.
Note: CMake doesn't ship with a Find Module for NetCDF, so you'll have to download one (like this one) from the internet. Then, you need to tell CMake where to locate this FindNetCDF.cmake file on your system using CMAKE_MODULE_PATH. Finally, you can use the NetCDF::NetCDF imported target to link NetCDF to your project's targets.
cmake_minimum_required(VERSION 3.10.0)
project(NUP Fortran)
# Don't need this, you already enabled Fortran above in the 'project' call.
enable_language(Fortran)
set(INCLUDE_FILE /usr/local/Cellar/netcdf/4.7.4/include)
set(lib_FILE /usr/local/Cellar/netcdf/4.7.4/lib)
# Add the location of the 'FindNetCDF.cmake' file to your module path.
list(APPEND CMAKE_MODULE_PATH "/path/to/downloaded/find/module")
# Then, call find package for NetCDF.
find_package(NetCDF REQUIRED)
if(${NetCDF_FOUND})
# Don't need this if you use the imported target below.
include_directories(${INCLUDE_FILE})
# Don't provide directories with source file list.
set(SOURCE_FILES
${PROJECT_BINARY_DIR}
unpack.f90
)
add_executable(NUP ${SOURCE_FILES})
# Use the imported target to link netcdf instead.
target_link_libraries(NUP PRIVATE NetCDF::NetCDF)
endif()
As commented, there are other approaches to adding NetCDF to your CMake project. If you use a different find module, the syntax of the provided NetCDF CMake variables and imported targets may be slightly different. You'll have to examine the find module file itself.
In addition, you may instead use a CMake package configuration file (e.g. netCDFConfig.cmake) downloaded from the internet to add NetCDF to your project. In this case, you would still use find_package(), but you would specify the configuration file's location using CMAKE_PREFIX_PATH, rather than CMAKE_MODULE_PATH.
You can find detailed descriptions for each of these approaches in the CMake find_package() documentation. I highly encourage you spend some time to read it.
I've got a cmake project that builds multiple executables and shared
libraries. There are option() settings that determine which of these
executables are built. What I'd like to be able to do is prevent the
building and installation of shared libraries that are not required. So
what I did is as follows:
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE) on the top level
CMakeLists file
add_library(${SHARED_LIBRARY} SHARED EXCLUDE_FROM_ALL ...)
install(TARGETS ${SHARED_LIBRARY} DESTINATION ${DESTINATION} OPTIONAL)
These three settings result in the desired behaviour. However, cmake
generates the following warning:
WARNING: Target "xxxx" has EXCLUDE_FROM_ALL set and will not be built by
default but an install rule has been provided for it. CMake does not
define behavior for this case.
Is this warning still valid in this specific scenario?
If so is there another/more correct way to achieve what I want?
If what I'm doing is acceptable, is there a way to suppress this
warning?
Thank you
I am pretty new to cmake and here is my CMakeLists.txt file on my project's root directory
cmake_minimum_required (VERSION 2.6)
project (Tools C)
set(CMAKE_C_FLAGS "-ansi -pedantic -Wall -Werror")
include_directories("include")
SET_SOURCE_FILES_PROPERTIES(lib/xstr.c PROPERTIES
OBJECT_DEPENDS "lib/xalloc.c")
SET_SOURCE_FILES_PROPERTIES(lib/counter.c PROPERTIES
OBJECT_DEPENDS "lib/xstr.c")
SET_SOURCE_FILES_PROPERTIES(lib/dynamic_array.c PROPERTIES
OBJECT_DEPENDS "lib/xalloc.c")
SET_SOURCE_FILES_PROPERTIES(lib/list.c PROPERTIES
OBJECT_DEPENDS "lib/xalloc.c")
add_executable(cat cat.c lib/xalloc.c lib/xfopen.c)
add_executable(counter counter.c lib/counter.c)
add_executable(darr dynamic_array.c lib/dynamic_array.c)
add_executable(linked list.c lib/list.c)
I keep c files that contains a main() function on my root directory. I keep other c files on {project_root}/lib directory.
My problem is that I am getting following error:
[ 33%] Built target cat
mingw32-make.exe[2]: *** No rule to make target 'lib/xstr.c', needed by 'CMakeFi
les/counter.dir/lib/counter.c.obj'. Stop.
CMakeFiles\Makefile2:94: recipe for target 'CMakeFiles/counter.dir/all' failed
mingw32-make.exe[1]: *** [CMakeFiles/counter.dir/all] Error 2
Makefile:75: recipe for target 'all' failed
mingw32-make.exe: *** [all] Error 2
What I want to achieve is to link{project_root}/cat.c with {project_root}/lib/xstr.c and {project_root}/lib/xalloc.c etc.
How can I achieve that?
You are taking cmake far too complicated! You have to set dependencies within targets, not source files. In your specific case, I suggest you add a few intermediate libraries. You can have them static so that the executable linking to them will not have problems in retrieving the linked library at runtime (the executable will integrate all the symbols and definitions he needs from the library).
Your code can be reduced as follow:
cmake_minimum_required (VERSION 2.8) # <<--2.6 is very outdated
project (Tools C)
set(CMAKE_C_FLAGS "-ansi -pedantic -Wall -Werror")
include_directories("include")
add_library(xalloc STATIC lib/xalloc.c)
add_library(xstr STATIC lib/xstr.c)
add_executable(cat cat.c lib/xfopen.c)
add_executable(counter counter.c lib/counter.c)
add_executable(darr dynamic_array.c lib/dynamic_array.c)
add_executable(linked list.c lib/list.c)
target_link_libraries(cat xalloc)
target_link_libraries(counter xstr xalloc) #xstr needs stuff from xalloc
target_link_libraries(darr xalloc)
target_link_libraries(linked xalloc)
Note: Are you sure you need darr and linked as executables? They look very much like a library... Also, having a file called counter.c and one lib/counter.c does not seem very safe (same for dynamic_array and list).
Some useful links:
http://www.cmake.org/cmake/help/v3.0/command/add_library.html
http://www.cmake.org/cmake/help/v3.0/command/target_link_libraries.html
I start using CMake to build my c++ source files, I see a strange comportament when I build inicially:
'cmake ../' will gerate the directory structure
'make' will build all
any successive make command will build nothing, as expected
'cmake ../' will apparent do nothing
'make' WILL REBUILD all
any successive make command will build nothing, as expected
There is my CMakelists.txt:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS "-Wall -pipe")
set(var_target CommonBase)
set(var_path_source base)
project(Prj_${var_target})
file(GLOB_RECURSE var_sources ${var_path_source}/*.cpp)
add_library(${var_target} SHARED ${var_sources})
install(TARGETS ${var_target} DESTINATION ${PROJECT_SOURCE_DIR}/install)
Looking better, at first 'cmake ../' command the file 'CMakeFiles/CommonBase.dir/depend.make' is empty, and the successive make command will insert the list of file dependencies
There is something wrong with my CMakelists.txt?
Thanks
There are a couple of issues here.
The actual cause of your problem is having the line set(CMAKE_CXX_FLAGS ...) before the project command.
The project command does quite a lot of work the first time it is run, and actually clears out this variable as a side-effect. So on your first run of CMake, the compiler flags are empty, and thereafter always contain what you set them to. (It's only the second time you run CMake which causes make to recompile all, not subsequent runs of CMake).
Try wrapping your project call with messages to see the effect:
message("CMAKE_CXX_FLAGS - ${CMAKE_CXX_FLAGS}")
project(Prj_${var_target})
message("CMAKE_CXX_FLAGS - ${CMAKE_CXX_FLAGS}")
Delete your CMakeCache.txt file (in your build root), then just run cmake .. repeatedly.
To fix this, move your set(CMAKE_CXX_FLAGS ...) to after the project command.
The second issue is that it's not recommended to set CMAKE_CXX_COMPILER in a CMakeLists.txt. Have a look at the comment below "Setting default compiler in CMake", and also the link there to CMake's FAQ entry How do I use a different compiler?