Linux out of tree module build issue - module

obj-m := $(MODNAME).o
ccflags-y := $(CCFLAGS)
src_files := $(wildcard $(foreach pat,*.c *.cpp *.s,src/$(pat) src/$(MODNAME)/$(pat)))
$(MODNAME)-objs := $(addsuffix .o, $(basename $(src_files)))
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean
I have this make file for building kernel modules. However whenever I run it, I get an error saying that there is no rule to make target .c. .c is not a source file. If I remove the "if [ -d src ]" check then I get an error saying src doesn't exists on the recursive make call from the kernel build system. If I specify the full path to src it gives the same output saying that it can't find it (which is really weird). If I hard code src_files it works (if I didn't copy and paste wrong). Does anybody have any idea what is going on?

In your makefile you expect current directory to be the one contained given makefile. But when your file is executed from Kbuild context, this is no longer true: current directory is directory with kernel sources.
That is why content of src_files variable becomes wrong: wildcard cannot find files under src/ in kernel sources. You may use special src variable for refer to directory with your makefile:
src_files := $(wildcard $(foreach pat,*.c *.cpp *.s,$(src)/src/$(pat) $(src)/src/$(MODNAME)/$(pat)))
From the other side, paths enumerated in *-objs variable should be relative (this is requirement by Kbuild). So you need to strip prefix from these absolute paths:
src_files_rel := $(src_files:$(src)/%=%)
Then you may use these paths for create objects list:
$(MODNAME)-objs := $(addsuffix .o, $(basename $(src_files_rel)))

Related

What's the use of configure_package_config_file option INSTALL_DESTINATION

For the following CMakeLists.txt file
cmake_minimum_required(VERSION 3.15)
project(Testing)
include(CMakePackageConfigHelpers)
configure_package_config_file(FooConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
INSTALL_DESTINATION lib/Goo/dmake
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
DESTINATION lib/Foo/cmake )
and the FooConfig.cmake.in file
#PACKAGE_INIT#
check_required_components(Foo)
It would finally install FooConfig.cmake to lib/Foo/cmake:
$ cmake ..
$ cmake --build .
$ cmake --install . --prefix ../install/
$ ls -R ../install/
../install/:
lib
../install/lib:
Foo
../install/lib/Foo:
cmake
../install/lib/Foo/cmake:
FooConfig.cmake
It seems that whatever value I set to the INSTALL_DESTINATION option of configure_package_config_file, it won't change FooConfig.cmake's installation directory. But if I comment INSTALL_DESTINATION lib/Goo/dmake, CMake Error prompts
No INSTALL_DESTINATION given to CONFIGURE_PACKAGE_CONFIG_FILE()
Then, what is the use of the INSTALL_DESINATION option? What its value (specifically, the above setting lib/Goo/dmake) actually affects?
The documentation:
The <path> given to INSTALL_DESTINATION must be the destination where the FooConfig.cmake file will be installed to.
I know the right way is INSTALL_DESTINATION lib/Foo/cmake. But as I deliberately set it as lib/Goo/dmake, the FooConfig.cmake file still rests at the desired destination lib/Foo/cmake. So, why this option is designed as a must?
The function configure_package_config_file only generates the file specified as the second argument. This function neither installs the generated file nor affects on its installation. So, its arguments can only affect on the content of the generated file.
If you look into the generated script FooConfig.cmake, then you could find the line like
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
This is how the script calculates installation prefix based on the path to the FooConfig.cmake file.
E.g. when you install the package with prefix /usr/local and your FooConfig.cmake script will be located in the directory /usr/local/lib/Foo/cmake, then the quoted path will be expanded into /usr/local/lib/Foo/cmake/../../../, which corresponds to /usr/local/.
Number of components ../ in the script equals to the number of components in INSTALL_DESTINATION parameter.
Why 'PACKAGE_PREFIX_DIR' is needed
Assume a package installs all public headers into directory include/ (relative to installation prefix), and config script needs to deliver that directory to the user via variable FOO_INCLUDE_DIR.
The most direct way would be to write in the script following:
# FooConfig.cmake.in
...
set(FOO_INCLUDE_DIR #CMAKE_INSTALL_PREFIX#/include)
so configure_package_config_file would substitute real install prefix instead of #CMAKE_INSTALL_PREFIX#.
But embedding absolute path into the config file prevents the package to be relocatable. So, once installed, the package could be used only from the installation directory, and cannot be copied elsewhere.
For relocatable package a config file computes all installation paths relative to the path of the config file itself, because it is the only path known to the script when it is called by find_package. It is like an executable can compute paths to the files located near to that executable.
If the script is installed into lib/Foo/cmake/FooConfig.cmake, then relative path to the include directory would be ../../../include, so one could use following assignment in that script:
# FooConfig.cmake.in
...
set(FOO_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../include)
So, when find_package(Foo) will execute this script, it expands the variable CMAKE_CURRENT_LIST_DIR to the actual directory with the possibly relocated script.
Operating with relative paths requires much attention from the coder, so CMake allows to automate this task:
# CMakeLists.txt
...
# Path to the include directory in the installation tree
set(INCLUDE_DIR 'include')
configure_package_config_file(FooConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
INSTALL_DESTINATION lib/Foo/cmake
# Tell CMake to handle variable `INCLUDE_DIR` as a path
# under installation tree.
PATH_VARS INCLUDE_DIR
)
# FooConfig.cmake.in
#PACKAGE_INIT#
# Here we could use `#PACKAGE_INCLUDE_DIR#` as reference
# to variable 'INCLUDE_DIR' set in the CMakeLists.txt.
set_and_check(FOO_INCLUDE_DIR "#PACKAGE_INCLUDE_DIR#")
If you look into the generated file, you will find that #PACKAGE_INCLUDE_DIR#
is expanded into ${PACKAGE_PREFIX_DIR}/include, which uses the variable PACKAGE_PREFIX_DIR.

Avoiding absolute paths in included cmake files [duplicate]

Suppose my project's CMakeLists.txt includes foo.cmake:
include(foo)
In foo.cmake, i want to know the path of foo.cmake.
How can I do that?
Note that CMAKE_CURRENT_LIST_DIR gives the directory of the including CMakeLists.txt, not that of the included foo.cmake, and is thus not what I want.
Of course, foo.cmake might be included by several projects (i.e., by several CMakeLists.txt files).
People have reported seemingly contradictory facts about how CMAKE_CURRENT_LIST_DIR behaves. Now I know the reason for the confusion:
First, in my Linux environment:
$ cd /path/to/home
$ mkdir cmake-test
$ cd cmake-test
$ mkdir source
$ mkdir source/subdirectory
$ mkdir build
I create these two files:
$ cat source/CMakeLists.txt
include(subdirectory/foo.cmake)
$ cat source/subdirectory/foo.cmake
message("CMAKE_CURRENT_LIST_DIR is ${CMAKE_CURRENT_LIST_DIR}")
CMake works as reported by Fraser and Robert Dailey:
$ cd build
$ cmake ../source
CMAKE_CURRENT_LIST_DIR is /path/to/home/cmake-test/source/subdirectory
[...]
However, I add a function to foo.cmake, which I call from CMakeLists.txt:
$ cat ../source/subdirectory/foo.cmake
message("CMAKE_CURRENT_LIST_DIR is ${CMAKE_CURRENT_LIST_DIR}")
function(bar)
message("CMAKE_CURRENT_LIST_DIR in bar() is ${CMAKE_CURRENT_LIST_DIR}")
endfunction()
$ cat ../source/CMakeLists.txt
include(subdirectory/foo.cmake)
bar()
Then:
$ cmake ../source
CMAKE_CURRENT_LIST_DIR is /path/to/home/cmake-test/source/subdirectory
CMAKE_CURRENT_LIST_DIR in bar() is /path/to/home/cmake-test/source
[...]
So, the value of CMAKE_CURRENT_LIST_DIR in foo.cmake is not the same at the time foo.cmake is included and when bar() is called. This is according to the specification of CMAKE_CURRENT_LIST_DIR.
Here is one possible solution for accessing the directory of foo.cmake from within bar():
$ cat ../source/subdirectory/foo.cmake
set(DIR_OF_FOO_CMAKE ${CMAKE_CURRENT_LIST_DIR})
function(bar)
message("DIR_OF_FOO_CMAKE in bar() is ${DIR_OF_FOO_CMAKE}")
endfunction()
after which I get the behavior I was looking for:
$ cmake ../source
DIR_OF_FOO_CMAKE in bar() is /path/to/home/cmake-test/source/subdirectory
[...]
In CMake 3.17, you have a new variable available, called CMAKE_CURRENT_FUNCTION_LIST_DIR, which can be used inside a function. It is undefined outside of a function definition.
function(foo)
configure_file(
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in"
some.output
)
endfunction()
Prior to CMake 3.17, CMAKE_CURRENT_FUNCTION_LIST_DIR functionality has to be approximated with CMAKE_CURRENT_LIST_DIR by the following workaround, taken from CMake documentation:
set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
function(foo)
configure_file(
"${_THIS_MODULE_BASE_DIR}/some.template.in"
some.output
)
endfunction()
See CMAKE_CURRENT_LIST_DIR:
Full directory of the listfile currently being processed.
As CMake processes the listfiles in your project this variable will
always be set to the directory where the listfile which is currently
being processed (CMAKE_CURRENT_LIST_FILE) is located. The value has
dynamic scope. When CMake starts processing commands in a source file
it sets this variable to the directory where this file is located.
When CMake finishes processing commands from the file it restores the
previous value. Therefore the value of the variable inside a macro or
function is the directory of the file invoking the bottom-most entry
on the call stack, not the directory of the file containing the macro
or function definition.
Example
I have the following structure:
C:\Work\cmake-test\CMakeLists.txt
C:\Work\cmake-test\subfolder\test.cmake
In my CMakeLists.txt:
include( subfolder/test.cmake )
In my test.cmake:
message( "Current dir: ${CMAKE_CURRENT_LIST_DIR}" )
The result I get when I run CMake from C:\Work\cmake-test is:
Current dir: C:/Work/cmake-test/subfolder
The include() command searches for modules in ${CMAKE_MODULE_PATH} first and then in CMake Modules dir.
So you can just check for file presence with if(EXISTS ${CMAKE_MODULE_PATH}/foo.cmake) and if(EXISTS ${CMAKE_ROOT}/Modules/foo.cmake).

Force CMake to use absolute include path

I have a project whose directory layout looks like:
- src/ #Contains main source code
- ext/ #Contains external libraries and headers from GitHub
- CMakeLists.txt
The problem is that no matter what I do, CMake always seems to pass ext/ to the compiler as a relative path, like this:
/usr/bin/c++ -I../ext mysrc.cpp
I've tried doing both:
include_directories("${PROJECT_SOURCE_DIR}/ext")
include_directories("/home/user/project/ext")
But it doesn't seem to matter. The directory is always passed to -I as ../ext.
Why does this matter? At the end of my build I invoke gcov -r <source file> which tells gcov to generate coverage reports from my source file and any relative paths found within. As a result, gcov is going into ext/ and generating reports for tons of stuff I don't care about and it's taking up a lot of time. If CMake would instead pass in -I/home/user/project/ext then gcov -r would ignore everything in ext/.
As far as I can tell from:
https://cmake.org/cmake/help/v3.13/command/include_directories.html ... this isn't possible, but maybe I'm just missing something?
Edit: This appears to be a problem with specifically the ninja generator. When using the Unix Makefiles generator, everything is passed via absolute paths.
https://gitlab.kitware.com/cmake/cmake/issues/18666
Edit2:
user#antimony:~/cmake_test$ ls
CMakeLists.txt ext src
user#antimony:~/cmake_test$ cat CMakeLists.txt
project(Hello)
add_subdirectory(src)
user#antimony:~/cmake_test$ cat src/CMakeLists.txt
include_directories(
.
${PROJECT_SOURCE_DIR}/ext
)
add_executable(hello_world hello.cpp)
user#antimony:~/cmake_test$ cat src/hello.cpp
#include <useless.h>
int main()
{
hello h;
return 0;
}
user#antimony:~/cmake_test$ cat ext/useless.h
struct hello {
int x;
};
user#antimony:~/cmake_test$ ~/Downloads/cmake-3.13.1-Linux-x86_64/bin/cmake --version
cmake version 3.13.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
user#antimony:~/cmake_test$ mkdir build && cd build
user#antimony:~/cmake_test/build$ ~/Downloads/cmake-3.13.1-Linux-x86_64/bin/cmake .. -G Ninja
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
...
-- Build files have been written to: /home/user/cmake_test/build
user#antimony:~/cmake_test/build$ ninja -v
[1/2] /usr/bin/c++ -I../src/. -I../ext -MD -MT src/CMakeFiles/hello_world.dir/hello.o -MF src/CMakeFiles/hello_world.dir/hello.o.d -o src/CMakeFiles/hello_world.dir/hello.o -c ../src/hello.cpp
[2/2] : && /usr/bin/c++ -rdynamic src/CMakeFiles/hello_world.dir/hello.o -o src/hello_world && :
user#antimony:~/cmake_test/build$ cat build.ninja
# CMAKE generated file: DO NOT EDIT!
# Generated by "Ninja" Generator, CMake Version 3.13
# This file contains all the build statements describing the
# compilation DAG.
...
#############################################
# Order-only phony target for hello_world
build cmake_object_order_depends_target_hello_world: phony || src/CMakeFiles/hello_world.dir
build src/CMakeFiles/hello_world.dir/hello.o: CXX_COMPILER__hello_world ../src/hello.cpp || cmake_object_order_depends_target_hello_world
DEP_FILE = src/CMakeFiles/hello_world.dir/hello.o.d
INCLUDES = -I../src/. -I../ext
OBJECT_DIR = src/CMakeFiles/hello_world.dir
OBJECT_FILE_DIR = src/CMakeFiles/hello_world.dir
TARGET_COMPILE_PDB = src/CMakeFiles/hello_world.dir/
TARGET_PDB = src/hello_world.pdb
# =============================================================================
# Link build statements for EXECUTABLE target hello_world
The example shows what may be considered an in-source build. That is when the build directory is the same or a sub-directory of the src folder (not that there is a hard definition or anything, but this does trigger the ninja issue of using relative paths on the command line). Try mkdir ~/cmake_build && cd ~/cmake_build && cmake ~/cmake_test then it should use absolute paths for everything.
Either way there really isn't a specific way to force one or the other. In general cmake generators will use absolute paths for everything that ends up used on the command line. There seems to be issues with Ninja that prevent the generator from using absolute paths for in-source builds (https://github.com/ninja-build/ninja/issues/1251).

CMake Error: file INSTALL destination is not a directory

I am running the command "sudo make install", the relevant cmake_install.cmake file is at the bottom. The exact error message I receive is:
CMake Error at cmake_install.cmake:36 (file):
file INSTALL destination:
~/Desktop/Geant/geant4.10.04-install/share/Geant4-10.4.0/geant4make is not
a directory.
Makefile:104: recipe for target 'install' failed
make: *** [install] Error 1
This is perplexing to me as I can navigate to that exact directory, it exists and whats more, it was made during this installation, so the make install is creating this directory and then saying that it doesn't exist...
Also, when I originally did the cmake command, my CMAKE_INSTALL_PREFIX is "~/Desktop/Geant/geant4.10.04-install", but since the make install command was able to make the geant4.10.04-install directory in the correct place, I don't think that is the problem.
The first 50ish lines of the cmake_install.cmake file (I can post the rest if need be...) :
# Install script for directory: /home/kagnew/Desktop/Geant/geant4.10.04
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "~/Desktop/Geant/geant4.10.04-install")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "Release")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Install shared libraries without execute permission?
if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
set(CMAKE_INSTALL_SO_NO_EXE "1")
endif()
if(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/Geant4-10.4.0/geant4make" TYPE FILE MESSAGE_LAZY PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE FILES "/home/kagnew/Desktop/Geant/geant4-build/InstallTreeFiles/geant4make.sh")
endif()
UPDATE: As suggested by Tsyvarev, changing the beginning of my prefix path from "~" to "/home/user/" seems to have fixed the problem
Using the environmental variable $ENV{HOME} is preferable to hardcoding /home/<user> because it will use the correct top-level directory (i.e. /Users instead of /home on macOS, if you're doing a cross-platform build), and it will automatically expand to include the name of the user invoking cmake, making it better suited to collaborative environments.
Additionally, using $ENV{HOME} should make the sudo in front of make install unnecessary, though depending on when the variable is expanded, $ENV{HOME} may refer to the user invoking cmake or the user invoking make install (i.e. /root if you use sudo), so your mileage may vary.
EDIT: I found my way to this question because I was getting the same "CMake Error: file INSTALL destination is not a directory" output due to using ~. It would seem that for certain purposes CMake just really doesn't like ~. $ENV{HOME} has exactly the same value as ~, except that CMake doesn't freak out when you try to use it in CMAKE_INSTALL_PREFIX.

cmake/cpack install command not adding my executable to my deb package

I'm having problems convincing cmake/cpack to generate a debian package that contains a single executable quine stored in a specific folder named /absolute/path.
According to https://cmake.org/cmake/help/v2.8.0/cmake.html#command:install I should be able to use an absolute path:
DESTINATION arguments specify the directory on disk to which a file
will be installed. If a full path (with a leading slash or drive
letter) is given it is used directly. If a relative path is given it
is interpreted relative to the value of CMAKE_INSTALL_PREFIX.
Here is my C file quine.c:
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
and my CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8)
project(quine)
file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
add_executable(quine ${SOURCES})
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Nobody")
install(
TARGETS quine
RUNTIME DESTINATION /absolute/path
)
include(CPack)
In an empty subdirectory called build I invoke the following:
$ cmake ..
$ make package
and the resulting package is only 512 bytes in length, and a:
$ dpkg -c quine-0.1.1-Linux.deb
confirms that the package is empty.
What am I doing wrong?