Initial import
This commit is contained in:
commit
0a5348b401
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,62 @@
|
|||
project(presentation LANGUAGES NONE)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# ------------------------------------
|
||||
|
||||
set(jobname "cmake-workshop-20190729")
|
||||
set(output "${jobname}.pdf")
|
||||
set(mainsource "main.tex")
|
||||
set(sources
|
||||
${mainsource}
|
||||
cmake-for-scripting.tex
|
||||
cross-compilation-toolchains.tex
|
||||
feature-platform-check.tex
|
||||
outro.tex
|
||||
preamble.tex
|
||||
project-handling.tex
|
||||
rpath-build-install-tree.tex
|
||||
starting-from-today.tex
|
||||
troubleshooting.tex
|
||||
usage-of-targets.tex)
|
||||
|
||||
file(GLOB images "images/*")
|
||||
list(APPEND sources ${images})
|
||||
|
||||
# ------------------------------------
|
||||
|
||||
find_program(XETEX NAMES xetex)
|
||||
if(NOT XETEX)
|
||||
message(FATAL_ERROR "Please install xetex")
|
||||
endif()
|
||||
|
||||
find_program(RUBBER NAMES rubber)
|
||||
if(NOT RUBBER)
|
||||
message(FATAL_ERROR "Please install rubber")
|
||||
endif()
|
||||
|
||||
find_program(PYGMENTS NAMES pygmentize)
|
||||
if(NOT PYGMENTS)
|
||||
message(FATAL_ERROR "Please install python3-pygments")
|
||||
endif()
|
||||
|
||||
|
||||
add_custom_command(OUTPUT ${output}
|
||||
COMMAND ${RUBBER} --unsafe --pdf
|
||||
--module xelatex
|
||||
--module beamer
|
||||
--module shell_escape
|
||||
--into ${CMAKE_CURRENT_BINARY_DIR}
|
||||
--jobname "${jobname}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${mainsource}"
|
||||
MAIN_DEPENDENCY ${mainsource}
|
||||
DEPENDS ${sources}
|
||||
BYPRODUCTS ${jobname}.aux
|
||||
${jobname}.nav
|
||||
${jobname}.toc
|
||||
${jobname}.log
|
||||
${jobname}.out
|
||||
${jobname}.snm
|
||||
COMMENT "Generating pdf file for the presentation"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(presentation ALL DEPENDS ${output})
|
|
@ -0,0 +1,215 @@
|
|||
|
||||
\begin{frame}
|
||||
\frametitle{CMake as a language}
|
||||
|
||||
\begin{center}
|
||||
\huge CMake as a language: variables, iterating, and functions
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{Variables}
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Setting variables}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
set(local_variable "a string")
|
||||
set(local_list "item1" "item2" "item3")
|
||||
set(another_local_list "item1;item2;item3")
|
||||
|
||||
set_property(GLOBAL PROPERTY
|
||||
A_GLOBAL_PROPERTY "${local_variable}")
|
||||
|
||||
# Not overridden if already in cache:
|
||||
set(CACHE_VARIABLE ${local_list}
|
||||
CACHE BOOL "Variable description")
|
||||
|
||||
# Always override, for our internal use:
|
||||
set(INTERNAL_CACHE_VARIABLE ${local_list}
|
||||
CACHE INTERNAL "Variable description")
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Scoping of variables}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
# in folder A
|
||||
set(local_variable "A")
|
||||
add_subdirectory("B")
|
||||
message(STATUS ${local_variable}) # -- prints A
|
||||
|
||||
# in folder B
|
||||
set(local_variable "B")
|
||||
message(STATUS ${local_variable}) # -- prints B
|
||||
\end{codebox}
|
||||
|
||||
\texttt{add\_subdirectory} introduces a new scope.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Scoping of variables -- propagating}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
# in folder A
|
||||
set(local_variable "A")
|
||||
add_subdirectory("B")
|
||||
message(STATUS ${local_variable}) # -- prints B
|
||||
|
||||
# in folder B
|
||||
set(local_variable "B" PARENT_SCOPE)
|
||||
message(STATUS ${local_variable}) # -- prints B
|
||||
\end{codebox}
|
||||
|
||||
\texttt{add\_subdirectory} introduces a new scope.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Scoping of variables -- caching}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
message(STATUS ${VARIABLE}) # 1st run: nothing, 2nd run: B
|
||||
add_subdirectory("C")
|
||||
|
||||
# in folder C
|
||||
set(VARIABLE "A")
|
||||
message(STATUS ${VARIABLE}) # 1st run: A, 2nd run: A
|
||||
set(VARIABLE "B" CACHE STRING "A looney var")
|
||||
message(STATUS ${VARIABLE}) # 1st run: B, 2nd run: A
|
||||
\end{codebox}
|
||||
|
||||
Note how, the second time, setting a variable in the cache
|
||||
is effectively a no-op, since it is already present there.
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{Conditionals and iterating}
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Conditionals}
|
||||
|
||||
\texttt{if} has a lot of comparison operators. Read the docs!
|
||||
|
||||
\vspace{.5em}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
# for historical reasons, unquoted variable
|
||||
# names are always expanded:
|
||||
if(var1 STREQUAL var2)
|
||||
# if true...
|
||||
|
||||
elseif("var1" STREQUAL "var2") # ... but not if quoted!
|
||||
# (never enters here)
|
||||
|
||||
else()
|
||||
# otherwise
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Iterating on lists}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
set(a_list "a" "b" "c")
|
||||
foreach(var IN LISTS a_list)
|
||||
message(STATUS ${var}) # prints on separate lines: a, b, c
|
||||
endforeach()
|
||||
|
||||
foreach(var IN ITEMS "one" "two" "three" ${a_list})
|
||||
message(STATUS ${var}) # prints on separate lines:
|
||||
# one, two, three, a, b, c
|
||||
endforeach()
|
||||
|
||||
# Note that quoted lists do not expand twice here:
|
||||
foreach(var IN ITEMS "${a_list}")
|
||||
message(STATUS ${var}) # prints on ONE line a;b;c
|
||||
endforeach()
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{Functions}
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Defining functions}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
function(f a b c)
|
||||
# here you can use a, b, and c.
|
||||
# ARGN is a magic list that contains all elements
|
||||
# provided after the third ("c").
|
||||
endfunction(f)
|
||||
|
||||
# Invocation:
|
||||
f("${var1}" "${var2}" "${var3}" "${var4}")
|
||||
|
||||
# This could lead to unexpected results with empty vars:
|
||||
f(${var1} ${var2} ${var3} ${var4})
|
||||
\end{codebox}
|
||||
|
||||
{\footnotesize Macros are like functions, but do not create a new
|
||||
scope. Plus assigning values to parameters is strange. Short
|
||||
rule: do \emph{not} use macros unless you know what you are
|
||||
doing.}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Returning values from functions}
|
||||
|
||||
There is no ``\texttt{return value}'' construct.
|
||||
|
||||
\vspace{.5em}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
function(identity VAR a)
|
||||
# We use VAR as the name of the return variable in the
|
||||
# parent scope.
|
||||
set("${VAR}" "${a}" PARENT_SCOPE)
|
||||
endfunction(identity)
|
||||
|
||||
# Invocation:
|
||||
set(a "value")
|
||||
identity(a "${a}")
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{Invoking as a script}
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Invoking a file as a script}
|
||||
|
||||
Why using CMake for scripting?
|
||||
|
||||
Well, it is more portable than bash across systems!
|
||||
|
||||
\vspace{.5em}
|
||||
|
||||
\begin{codebox}{Bash}{}
|
||||
$ cmake -DVAR1="value1" ... -P script-name.cmake
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
|
@ -0,0 +1,49 @@
|
|||
# Install script for directory: /home/matteo/cmake-presentation
|
||||
|
||||
# Set the install prefix
|
||||
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX "/usr/local")
|
||||
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 "")
|
||||
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()
|
||||
|
||||
# Is this installation the result of a crosscompile?
|
||||
if(NOT DEFINED CMAKE_CROSSCOMPILING)
|
||||
set(CMAKE_CROSSCOMPILING "FALSE")
|
||||
endif()
|
||||
|
||||
if(CMAKE_INSTALL_COMPONENT)
|
||||
set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
|
||||
else()
|
||||
set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
|
||||
"${CMAKE_INSTALL_MANIFEST_FILES}")
|
||||
file(WRITE "/home/matteo/cmake-presentation/${CMAKE_INSTALL_MANIFEST}"
|
||||
"${CMAKE_INSTALL_MANIFEST_CONTENT}")
|
|
@ -0,0 +1,104 @@
|
|||
\subsection{Cross-Compilation, Toolchain files}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Cross-compilation}
|
||||
|
||||
\begin{center}
|
||||
\huge Dealing with different platforms
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Cross-Compilation, Concepts}
|
||||
Building binaries for a platform other than the one on which the
|
||||
compiler runs.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\textbf {Host Platform} \\
|
||||
{\info {Platform/System \textbf {ON} which the binaries are built, compiler(cross-compiler) runs.}}
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\textbf{Target Platform} \\
|
||||
{\info {Platform \textbf {FOR} which the binaries are built.}}
|
||||
\end{frame}
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Cross-Compilation, Concepts}
|
||||
\textbf {Toolchain}\\
|
||||
{\info {Set of tools and libraries to built binaries for a target platform, such as:}
|
||||
\begin{itemize}
|
||||
\item Binutils
|
||||
\item Cross Compiler
|
||||
\item C Library
|
||||
\item Debugger
|
||||
\end{itemize}
|
||||
}
|
||||
\end{frame}
|
||||
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{CMake \& Cross-Compilation}
|
||||
CMake needs help to recognize Cross-Compilation, e.g.\\
|
||||
\begin{itemize}
|
||||
\item Target System Name
|
||||
\item Cross Compiler Location
|
||||
\item Library Search Paths
|
||||
\item etc.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{CMake \& Cross-Compilation}
|
||||
|
||||
\textbf {Toolchain Files} - CMake Script enclosing toolchain info.
|
||||
|
||||
E.g.:
|
||||
|
||||
\begin{itemize}
|
||||
\item Target System Name -- {\code CMAKE\_SYSTEM\_NAME}
|
||||
\item Cross-Compiler to be used -- {\code CMAKE\_C\_COMPILER}
|
||||
\item Library and Package search root -- {\code {CMAKE\_FIND\_ROOT\_PATH}}
|
||||
\item Default compiler and linker flags specific to the target platform
|
||||
\end{itemize}
|
||||
|
||||
{\info {\code {CMAKE\_TOOLCHAIN\_FILE}} used to provide toolchain file location}
|
||||
\end{frame}
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{CMake \& Cross-Compilation}
|
||||
|
||||
System introspection is still possible while cross-compiling:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\code {try\_compile}} - works as expected
|
||||
\item {\code {try\_run}} - limited functionality, run phase is usually skipped
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
%--------------------------------------------------------------------------------------------------
|
||||
|
||||
\note{
|
||||
What is cross-compilation
|
||||
HOST, TARGET, compilers
|
||||
Toolchain files
|
||||
- meaning and content
|
||||
Cross compilation with cmake
|
||||
- CMAKE Variables
|
||||
- Searching \& finding packages
|
||||
- toolchain files
|
||||
- system introspection (try-compile, try-run)
|
||||
- HOST-TOOLS, why might be required
|
||||
- Using Executables in the build created during the build
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
# cmake_minimum_required(VERSION 3.11)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
|
||||
## Declare a project named "cmake-exercise"
|
||||
project(cmake-exercise VERSION 0.90.0)
|
||||
|
||||
if(CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Don't build in the source directory, pretty please.")
|
||||
endif()
|
||||
|
||||
## Includes
|
||||
include(GNUInstallDirs)
|
||||
include(GenerateExportHeader)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
## Find necessary packages
|
||||
find_package(OpenMP)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
## Artifacts to create
|
||||
add_library(obj OBJECT)
|
||||
add_library(static STATIC)
|
||||
add_library(shared SHARED)
|
||||
add_library(interface INTERFACE)
|
||||
add_executable(tests)
|
||||
|
||||
## Generate other files
|
||||
generate_export_header(shared
|
||||
BASE_NAME DSO
|
||||
EXPORT_FILE_NAME include/cmake-exercise/config.hh)
|
||||
|
||||
## Specify source files
|
||||
target_sources(obj
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/cmake-exercise/a.hh>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cmake-exercise/a.hh>
|
||||
PRIVATE src/a.cc)
|
||||
target_sources(shared
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/cmake-exercise/b.hh>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cmake-exercise/b.hh>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include/cmake-exercise/config.hh>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cmake-exercise/config.hh>
|
||||
PRIVATE src/b.cc
|
||||
$<TARGET_PROPERTY:obj,INTERFACE_SOURCES>
|
||||
$<TARGET_OBJECTS:obj>)
|
||||
target_sources(interface
|
||||
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/cmake-exercise/c.hh>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cmake-exercise/c.hh>)
|
||||
target_sources(tests
|
||||
PRIVATE test/test.cc)
|
||||
|
||||
|
||||
## Add include folders
|
||||
target_include_directories(interface
|
||||
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
target_include_directories(obj
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
target_include_directories(shared
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
|
||||
## Set target properties for visibility and PIC
|
||||
set_property(TARGET obj PROPERTY POSITION_INDEPENDENT_CODE TRUE)
|
||||
set_property(TARGET obj shared PROPERTY CXX_VISIBILITY_PRESET hidden)
|
||||
set_property(TARGET obj shared PROPERTY VISIBILITY_INLINES_HIDDEN TRUE)
|
||||
|
||||
|
||||
## Specify C++ version to use
|
||||
target_compile_features(interface
|
||||
INTERFACE cxx_std_11)
|
||||
target_compile_features(obj
|
||||
INTERFACE cxx_std_11
|
||||
PRIVATE cxx_std_14)
|
||||
|
||||
|
||||
## Link to other libraries, and inherit their settings
|
||||
target_link_libraries(obj
|
||||
PUBLIC Threads::Threads)
|
||||
target_link_libraries(static
|
||||
PRIVATE interface
|
||||
PUBLIC obj)
|
||||
target_link_libraries(shared
|
||||
PRIVATE interface obj)
|
||||
target_link_libraries(tests
|
||||
PRIVATE static)
|
||||
|
||||
if(TARGET OpenMP::OpenMP_CXX)
|
||||
target_compile_definitions(tests PRIVATE HAVE_OPENMP)
|
||||
target_link_libraries(tests PRIVATE OpenMP::OpenMP_CXX)
|
||||
endif()
|
||||
|
||||
|
||||
## Install all needed files for packaging
|
||||
install(FILES $<TARGET_PROPERTY:shared,INTERFACE_SOURCES>
|
||||
$<TARGET_PROPERTY:interface,INTERFACE_SOURCES>
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
COMPONENT devel)
|
||||
install(TARGETS shared
|
||||
EXPORT cmake-exercise
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(TARGETS obj interface
|
||||
EXPORT cmake-exercise
|
||||
COMPONENT devel
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(TARGETS tests
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake-exercise/test
|
||||
COMPONENT test)
|
||||
|
||||
## Add a test
|
||||
enable_testing()
|
||||
add_test(NAME not-really-a-test
|
||||
COMMAND tests --ignored-param)
|
||||
|
||||
|
||||
## Generate the export sets to be able to import this project
|
||||
## in other projects via find_package (the config file is not complete though)
|
||||
set(CMAKE_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/cmake-exercise)
|
||||
export(EXPORT cmake-exercise
|
||||
NAMESPACE cmake-exercise::
|
||||
FILE cmake-exercise-targets.cmake)
|
||||
install(EXPORT cmake-exercise
|
||||
NAMESPACE cmake-exercise::
|
||||
DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
|
||||
FILE cmake-exercise-targets.cmake
|
||||
COMPONENT devel)
|
||||
configure_package_config_file(cmake-exercise-config.cmake.in
|
||||
cmake-exercise-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_CMAKEDIR})
|
||||
write_basic_package_version_file(cmake-exercise-version.cmake
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake-exercise-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake-exercise-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
|
||||
COMPONENT devel)
|
||||
|
||||
|
||||
## Trigger packaging
|
||||
set(CPACK_PACKAGE_FILE_NAME package)
|
||||
set(CPACK_GENERATOR TXZ)
|
||||
set(CPACK_ARCHIVE_COMPONENT_INSTALL TRUE)
|
||||
include(CPack)
|
|
@ -0,0 +1,6 @@
|
|||
This is a simple exercise to get familiar a bit with CMake.
|
||||
|
||||
See the deployment diagram in doc/ to know what is the final result
|
||||
should look like.
|
||||
|
||||
Other than that, follow the comments in CMakeLists.txt
|
|
@ -0,0 +1,3 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake-exercise-targets.cmake)
|
Binary file not shown.
After Width: | Height: | Size: 183 KiB |
|
@ -0,0 +1,119 @@
|
|||
@startuml
|
||||
left to right direction
|
||||
|
||||
hide <<Layout>> stereotype
|
||||
skinparam rectangle<<Layout>> {
|
||||
borderColor Transparent
|
||||
backgroundColor Transparent
|
||||
fontColor Transparent
|
||||
shadowing false
|
||||
}
|
||||
|
||||
folder "source directory" as srcdir {
|
||||
folder "include/cmake-exercise" as include_srcdir {
|
||||
file a.hh
|
||||
file b.hh
|
||||
file c.hh
|
||||
}
|
||||
|
||||
folder "src" {
|
||||
file a.cc
|
||||
file b.cc
|
||||
}
|
||||
|
||||
folder "test" as test_srcdir {
|
||||
file test.cc
|
||||
}
|
||||
|
||||
file CMakeLists.txt
|
||||
}
|
||||
|
||||
folder "build directory" as builddir {
|
||||
rectangle folders_layout <<Layout>> {
|
||||
folder "src" as src_builddir {
|
||||
file a.o
|
||||
file b.o
|
||||
}
|
||||
|
||||
folder "test" as test_builddir {
|
||||
file test.o
|
||||
}
|
||||
|
||||
folder "include/cmake-exercise" as include_builddir {
|
||||
file config.hh
|
||||
}
|
||||
}
|
||||
|
||||
rectangle artifacts_layout <<Layout>> {
|
||||
artifact "<<static library>>\nlibstatic.a" as static
|
||||
artifact "<<shared library>>\nlibshared.so" as shared
|
||||
artifact "<<executable>>\ntest-binary" as test
|
||||
|
||||
static -[hidden]r- shared
|
||||
shared -[hidden]r- test
|
||||
}
|
||||
}
|
||||
|
||||
srcdir -[hidden]r- builddir
|
||||
|
||||
package package.tar.xz {
|
||||
folder "<prefix>/include/cmake-exercise" {
|
||||
file a.hh as installed_a.hh
|
||||
file b.hh as installed_b.hh
|
||||
file c.hh as installed_c.hh
|
||||
file config.hh as installed_config.hh
|
||||
}
|
||||
|
||||
folder "<prefix>/share/cmake-exercise/test" {
|
||||
artifact "<<executable>>\ntest" as installed_test
|
||||
}
|
||||
|
||||
folder "<prefix>/lib" {
|
||||
artifact "<<shared library>>\nlibshared.so" as installed_shared
|
||||
}
|
||||
}
|
||||
|
||||
actor CMake
|
||||
|
||||
a.hh --> installed_a.hh : <<install>>
|
||||
b.hh --> installed_b.hh : <<install>>
|
||||
c.hh --> installed_c.hh : <<install>>
|
||||
config.hh --> installed_config.hh : <<install>>
|
||||
test --> installed_test : <<install>>
|
||||
shared --> installed_shared : <<install>>
|
||||
|
||||
file "<<source>>\na.cc" as a.cc
|
||||
file "<<source>>\nb.cc" as b.cc
|
||||
file "<<source>>\na.hh" as a.hh
|
||||
file "<<source>>\nb.hh" as b.hh
|
||||
file "<<source>>\nc.hh" as c.hh
|
||||
file "<<source>>\nconfig.hh" as config.hh
|
||||
|
||||
file "<<file>>\na.o" as a.o
|
||||
file "<<file>>\nb.o" as b.o
|
||||
file "<<file>>\ntest.o" as test.o
|
||||
|
||||
file "<<source>>\ntest.cc" as test.cc
|
||||
|
||||
CMake -u-> config.hh : <<generate>>
|
||||
|
||||
a.cc --> a.o : <<compile>>
|
||||
b.cc --> b.o : <<compile>>
|
||||
test.cc --> test.o : <<compile>>
|
||||
|
||||
test ..> test.o : <<link>>
|
||||
test ..> static : <<link>>
|
||||
static ..> a.o : <<archive>>
|
||||
shared ..> a.o : <<link>>
|
||||
shared ..> b.o : <<link>>
|
||||
|
||||
b.hh ~r~> a.hh : <<include>>
|
||||
a.hh ~~> c.hh : <<include>>
|
||||
b.hh ~~> c.hh : <<include>>
|
||||
a.hh ~~> config.hh : <<include>>
|
||||
b.hh ~~> config.hh : <<include>>
|
||||
a.cc ~~> a.hh : <<include>>
|
||||
b.cc ~~> b.hh : <<include>>
|
||||
test.cc ~~> a.hh : <<include>>
|
||||
|
||||
@enduml
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
A ();
|
||||
A (A&&) = default;
|
||||
~A ();
|
||||
|
||||
A& operator= (A&&) = default;
|
||||
|
||||
private:
|
||||
std::thread _t;
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <cmake-exercise/a.hh>
|
||||
|
||||
#include <cmake-exercise/config.hh>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class B
|
||||
{
|
||||
public:
|
||||
DSO_EXPORT B ();
|
||||
|
||||
private:
|
||||
std::vector<A> _a;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
template <typename T>
|
||||
void unused_function (); // nothing to see here
|
|
@ -0,0 +1,31 @@
|
|||
#include <cmake-exercise/a.hh>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
A::A ()
|
||||
: _t ([] ()
|
||||
{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Starting thread " << std::this_thread::get_id () << std::endl;
|
||||
std::cout << oss.str() << std::flush;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(std::rand() % 100 * 10));
|
||||
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Thread " << std::this_thread::get_id () << " finished" << std::endl;
|
||||
std::cout << oss.str() << std::flush;
|
||||
}
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
A::~A ()
|
||||
{
|
||||
_t.join ();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <cmake-exercise/b.hh>
|
||||
#include <cmake-exercise/c.hh>
|
||||
|
||||
B::B ()
|
||||
: _a (10)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include <cmake-exercise/a.hh>
|
||||
|
||||
#include <vector>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
// not a real test, heh.
|
||||
#ifdef HAVE_OPENMP
|
||||
# pragma omp parallel for
|
||||
for (int n = 0; n < 20; ++n)
|
||||
{
|
||||
A a;
|
||||
}
|
||||
|
||||
#else
|
||||
std::vector<A> a (20);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
\subsection{Feature vs. Platform Checks}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Feature checks}
|
||||
|
||||
\begin{center}
|
||||
\huge Probing the outside system\\for capabilities
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{What's a ``Feature''}
|
||||
Distinctive attribute which may have influence on the final system being built.\\
|
||||
\\
|
||||
Can be classified in 3 domains:
|
||||
\begin{itemize}
|
||||
\item Platform features\\
|
||||
{\info {library, symbols, functions, type size}}
|
||||
\item Compiler features\\
|
||||
{\info {variadic templates, constexpr, final, override}}
|
||||
\item System dictated features\\
|
||||
{\info {no-exceptions, no-rtti, no logging}}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle {Platform specific feature check}
|
||||
|
||||
\textbf{Bad}
|
||||
\begin{codebox}{CMake}{}
|
||||
if(IOS OR ANDROID OR UNIX)
|
||||
target_compile_definitions(lua PRIVATE HAVE_POSIX_SPAWN)
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\textbf{Good}
|
||||
\begin{codebox}{CMake}{}
|
||||
check_symbol_exists("posix_spawn" "spawn.h" has_posix_spawn)
|
||||
if(has_posix_spawn)
|
||||
target_compile_definitions(lua PRIVATE HAVE_POSIX_SPAWN)
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle {Compiler specific feature checks}
|
||||
|
||||
\textbf{Bad}
|
||||
\begin{codebox}[minted options={fontsize=\tiny}]{CMake}{}
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
target_compile_definitions(my-library
|
||||
PRIVATE -DBOOST_THREAD_DONT_USE_CHRONO)
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\textbf{Good}
|
||||
\begin{codebox}[minted options={fontsize=\tiny}]{CMake}{}
|
||||
# (incomplete example, checking for exception support is slightly harder)
|
||||
check_cxx_source_compile("
|
||||
int main() {
|
||||
#if !defined(__EXCEPTIONS)
|
||||
#error Exceptions not supported.
|
||||
#endif
|
||||
}" exceptions_supported)
|
||||
|
||||
if(NOT exceptions_supported)
|
||||
target_compile_definitions(my-library
|
||||
PRIVATE -DBOOST_THREAD_DONT_USE_CHRONO)
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle {System dictated feature checks}
|
||||
|
||||
\textbf{Bad}
|
||||
\begin{codebox}[minted options={fontsize=\scriptsize}]{CMake}{}
|
||||
find_package(Boost)
|
||||
if(Boost_FOUND)
|
||||
add_definition(ENABLE_FEATURE_X)
|
||||
endif()
|
||||
\end{codebox}
|
||||
|
||||
\textbf {Good}
|
||||
\begin{codebox}[minted options={fontsize=\scriptsize}]{CMake}{}
|
||||
# In product config file
|
||||
set(ENABLE_FEATURE_X TRUE)
|
||||
|
||||
# In project configuration
|
||||
if(ENABLE_FEATURE_X)
|
||||
find_package(Boost REQUIRED)
|
||||
add_definition(FEATURE_X_ENABLED)
|
||||
endif()
|
||||
\end{codebox}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Functions for configure checks}
|
||||
|
||||
CMake provides an API to check:
|
||||
|
||||
\begin{itemize}
|
||||
\item Header existence: {\code{check\_include\_file()}}
|
||||
\item Library existence: {\code{check\_library\_exists()}}
|
||||
\item Symbol existence: {\code{check\_symbol\_exists()}}
|
||||
\item Supported type sizes: {\code{check\_type\_size()}}
|
||||
\end{itemize}
|
||||
|
||||
CMake provides an API to write custom checks via:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\code{try\_compile()}}
|
||||
\item {\code{try\_run()}}
|
||||
\end{itemize}
|
||||
|
||||
With {\code configure\_file} you can generate a header file
|
||||
enabling required code switches based on the checks.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\note{
|
||||
What is Platform check
|
||||
What is feature check
|
||||
CMAKE system introspection interface
|
||||
-What type of checks can be done with CMAKE
|
||||
https://cmake.org/Wiki/CMake:How\_To\_Write\_Platform\_Checks
|
||||
Pros and Cons
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,82 @@
|
|||
%\documentclass[notes,usenames,dvipsnames]{beamer}
|
||||
\documentclass[usenames,dvipsnames]{beamer}
|
||||
%\documentclass[usenames,dvipsnames,handout]{beamer}
|
||||
|
||||
\input{preamble}
|
||||
|
||||
% for the handout
|
||||
\usepackage{pgfpages}
|
||||
\setbeamertemplate{headline}{}
|
||||
\addtobeamertemplate{navigation symbols}{}{%
|
||||
\usebeamerfont{footline}%
|
||||
\usebeamercolor[fg]{footline}%
|
||||
\hspace{1em}%
|
||||
\insertframenumber/\inserttotalframenumber
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
urlcolor=cyan
|
||||
}
|
||||
|
||||
\title{Introduction to CMake}
|
||||
\author[M. Settenvini] {
|
||||
Matteo Settenvini \\
|
||||
$\langle$\href{mailto:matteo@member.fsf.org}{matteo@member.fsf.org}$\rangle$
|
||||
}
|
||||
|
||||
\date{\today}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\begin{columns}[T]
|
||||
\begin{column}{.5\textwidth}
|
||||
\titlepage
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\node (logo) {\includegraphics[width=.6\textwidth]{images/cmake-logo.png}};
|
||||
\node (eye) at ([shift={(logo)}] -90:.55) {\includegraphics[width=.3\textwidth]{images/eye-of-god.png}};
|
||||
\end{tikzpicture}
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\end{center}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Table of Contents}
|
||||
|
||||
\begin{multicols}{2}
|
||||
\footnotesize
|
||||
\tableofcontents
|
||||
\end{multicols}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\section{CMake as a language}
|
||||
\input{cmake-for-scripting}
|
||||
|
||||
\section{Setting up a CMake project}
|
||||
\input{usage-of-targets}
|
||||
\input{project-handling}
|
||||
|
||||
\section{Starting from today}
|
||||
\input{starting-from-today}
|
||||
|
||||
\section{Outro}
|
||||
\input{outro}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,13 @@
|
|||
% --------------------------------------------------
|
||||
|
||||
\subsection{Q\&A}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Q\&A}
|
||||
|
||||
\begin{center}
|
||||
\huge Questions?
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
|
@ -0,0 +1,145 @@
|
|||
\usepackage{fontspec}
|
||||
\usepackage{polyglossia}
|
||||
\usepackage[justification=centering]{caption}
|
||||
\usepackage{graphics}
|
||||
\usepackage[listings,skins,minted]{tcolorbox}
|
||||
\usepackage{etoolbox,xpatch}
|
||||
\usepackage{multicol}
|
||||
|
||||
\setdefaultlanguage{english}
|
||||
|
||||
\newfontfamily\emotifont{Noto Emoji}
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
% new commands
|
||||
\newcommand\hint[1]{\tiny \color{Black} {#1}\\}
|
||||
\newcommand\todo[1]{\tiny \color{Red} {TODO: #1}\\}
|
||||
\newcommand\code[1]{\scriptsize \ttfamily \color{blue} {#1}}
|
||||
\newcommand\info[1]{\scriptsize \slshape {#1}}
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
% style thingies
|
||||
\usetheme{Malmoe}
|
||||
|
||||
\tikzset{
|
||||
every overlay node/.style={
|
||||
rounded corners,anchor=north west,
|
||||
},
|
||||
}
|
||||
% Usage:
|
||||
% \tikzoverlay at (-1cm,-5cm) {content};
|
||||
% or
|
||||
% \tikzoverlay[text width=5cm] at (-1cm,-5cm) {content};
|
||||
\def\tikzoverlay{%
|
||||
\tikz[baseline,overlay]\node[every overlay node]
|
||||
}%
|
||||
|
||||
|
||||
\addtobeamertemplate{headline}{}{%
|
||||
\tikzoverlay at (-.97\textwidth,.18\textheight) {%
|
||||
\includegraphics[height=.15\textheight,keepaspectratio]{images/cmake-logo.png}%
|
||||
};
|
||||
}
|
||||
|
||||
\definecolor{herenavy}{RGB}{15,22,33}
|
||||
\definecolor{hereblue}{RGB}{72,218,208}
|
||||
|
||||
\setbeamercolor{structure}{fg=herenavy}
|
||||
|
||||
\setbeamercolor{palette primary}{fg=white,bg=herenavy!70}
|
||||
\setbeamercolor{palette secondary}{fg=white,bg=herenavy!80}
|
||||
\setbeamercolor{palette tertiary}{fg=white,bg=herenavy!90}
|
||||
\setbeamercolor{palette quaternary}{fg=white,bg=herenavy}
|
||||
|
||||
\setbeamercolor{titlelike}{parent=palette quaternary}
|
||||
|
||||
\setbeamercolor{subsection in head/foot}{bg=herenavy!90}
|
||||
|
||||
\setbeamercolor{block title}{fg=white,bg=herenavy}
|
||||
\setbeamercolor{block title alerted}{use=alerted text,fg=white,bg=alerted text.fg!75!bg}
|
||||
\setbeamercolor{block title example}{use=example text,fg=white,bg=example text.fg!75!bg}
|
||||
|
||||
\setbeamercolor{block body}{parent=normal text,use=block title,bg=block title.bg!25!bg}
|
||||
\setbeamercolor{block body alerted}{parent=normal text,use=block title alerted,bg=block title alerted.bg!25!bg}
|
||||
\setbeamercolor{block body example}{parent=normal text,use=block title example,bg=block title example.bg!25!bg}
|
||||
|
||||
\setbeamercolor{sidebar}{bg=hereblue!70}
|
||||
|
||||
\setbeamercolor{palette sidebar primary}{fg=herenavy}
|
||||
\setbeamercolor{palette sidebar secondary}{fg=herenavy!75}
|
||||
\setbeamercolor{palette sidebar tertiary}{fg=herenavy!75}
|
||||
\setbeamercolor{palette sidebar quaternary}{fg=herenavy}
|
||||
|
||||
\setbeamercolor*{separation line}{}
|
||||
\setbeamercolor*{fine separation line}{}
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
\newcommand\fullscreenimage[2]{
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\textwidth,height=.7\textheight,keepaspectratio]{#1}
|
||||
\caption*{\tiny #2}
|
||||
\end{figure}
|
||||
}
|
||||
|
||||
% ---------------------------------------------------------------------
|
||||
|
||||
% Listings stuff
|
||||
|
||||
\newcommand{\mynewminted}[3]{%
|
||||
\newminted[#1]{#2}{#3}%
|
||||
\tcbset{myminted/#1/.style={minted language=#2,minted options={#3}}}}
|
||||
|
||||
\mynewminted{CMake}{cmake}{tabsize=2,fontsize=\footnotesize}
|
||||
\mynewminted{C++}{cpp}{tabsize=4,fontsize=\footnotesize}
|
||||
\mynewminted{Bash}{bash}{tabsize=2,fontsize=\footnotesize}
|
||||
\mynewminted{Shell}{shell-session}{tabsize=2,fontsize=\footnotesize,breaklines}
|
||||
|
||||
|
||||
\newtcblisting{codebox}[3][]{%
|
||||
listing only,%
|
||||
title={#3},%
|
||||
enhanced,%
|
||||
colback=structure.bg!20,%
|
||||
colframe=black!60,%
|
||||
drop fuzzy shadow,%
|
||||
myminted/#2,%
|
||||
#1}
|
||||
|
||||
\newtcblisting{goodcodebox}[2][]{%
|
||||
listing only,%
|
||||
title={Good},%
|
||||
enhanced,%
|
||||
top=.3em,%
|
||||
left=.3em,%
|
||||
fonttitle=\tiny\bfseries,%
|
||||
colback=structure.bg!20,%
|
||||
colframe=green!80!black!90,%
|
||||
drop fuzzy shadow,%
|
||||
myminted/#2,%
|
||||
minted options={fontsize=\tiny},%
|
||||
#1}
|
||||
|
||||
\newtcblisting{badcodebox}[2][]{%
|
||||
listing only,%
|
||||
title={Bad},%
|
||||
enhanced,%
|
||||
top=.3em,%
|
||||
left=.3em,%
|
||||
fonttitle=\tiny\bfseries,%
|
||||
colback=structure.bg!20,%
|
||||
colframe=red!90!black!90,%
|
||||
drop fuzzy shadow,%
|
||||
myminted/#2,%
|
||||
minted options={fontsize=\tiny},%
|
||||
#1}
|
||||
|
||||
% We ignore parsing errors as part of this presentation
|
||||
\makeatletter
|
||||
\AtBeginEnvironment{minted}{\dontdofcolorbox}
|
||||
\def\dontdofcolorbox{\renewcommand\fcolorbox[4][]{##4}}
|
||||
\xpatchcmd{\inputminted}{\minted@fvset}{\minted@fvset\dontdofcolorbox}{}{}
|
||||
\makeatother
|
|
@ -0,0 +1,6 @@
|
|||
\input{rpath-build-install-tree}
|
||||
\input{cross-compilation-toolchains}
|
||||
\input{feature-platform-check}
|
||||
\input{troubleshooting}
|
||||
|
||||
% --------------------------------------------------------------------
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
\begin{frame}
|
||||
\frametitle{Relocatable binaries and resources}
|
||||
|
||||
\begin{center}
|
||||
\huge Making packages relocatable
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{rpath}
|
||||
|
||||
Runtime search path - embedded in the binaries
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\includegraphics[width=.95\textwidth,keepaspectratio]{images/so_rpath.png}
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\includegraphics[width=.95\textwidth,keepaspectratio]{images/dylib_rpath.png}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{rpath}
|
||||
|
||||
Used by the Dynamic Linker (DL) on UNIX systems
|
||||
|
||||
\begin{itemize}
|
||||
\item rpath - almost the first place to look for the libraries,
|
||||
\newline nowadays {\code{DT\_RUNPATH}} is more common than
|
||||
{\code{DT\_RPATH}} as a tag
|
||||
\item Search path sequence for DL -
|
||||
{\code{RPATH, LD\_LIBRARY\_PATH, RUNPATH, /etc/ld.so.conf, /lib/,
|
||||
/usr/lib}, …}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{rpath}
|
||||
|
||||
\begin{itemize}
|
||||
\item Can be overwritten - {\code {chrpath, patchelf}}
|
||||
\item Can be extracted - {\code {objdump, readelf, otool, etc.}}
|
||||
\end{itemize}
|
||||
|
||||
\begin{codebox}{Shell}{}
|
||||
$ objdump -x <path-to-library> | grep RPATH
|
||||
$ readelf -d <path-to-library> | grep RPATH
|
||||
$ otool -L <path-to-library>
|
||||
\end{codebox}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{rpath}
|
||||
|
||||
\begin{tabular}{ | p{5cm} | p{5cm} |}
|
||||
\hline
|
||||
{\textbf {In Build Tree}} & {\textbf {In Install Tree}} \\
|
||||
\hline
|
||||
{Points to directories in the build folder
|
||||
{\begin{itemize}
|
||||
\item Usually full paths
|
||||
\item Updated while installing
|
||||
\end{itemize}}} &
|
||||
{Points to directories specified during build for installation
|
||||
{\begin{itemize}
|
||||
\item Can be full path
|
||||
\item Can be relative path
|
||||
\item Can be empty
|
||||
\end{itemize}}} \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle {Relocatable packages}
|
||||
Relative or empty rpaths when installed
|
||||
\begin{itemize}
|
||||
\item {\code \$ORIGIN} - *nix OSs
|
||||
\item {\code @rpath} (+ {\code @loader\_path}, {\code @executable\_path}) - Mac OSX \& IOS
|
||||
\item Always Empty - Android\\
|
||||
{\info {Usually libraries are packed with {\code APK} and loaded using {\code
|
||||
dlopen} interface\\}}
|
||||
\item Always Empty - for Windows\\
|
||||
{\info {Only user account and system env paths are
|
||||
searched for libraries, plus the current folder\\}}
|
||||
\end{itemize}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Making loading resources relocatable}
|
||||
|
||||
Resources used by package should be easily locatable\\
|
||||
|
||||
\textbf{Bad:} when resource paths are hardcoded in the source code\\
|
||||
|
||||
\textbf{Good:} when resource paths are dynamically determined at runtime\\
|
||||
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Making loading resources relocatable}
|
||||
|
||||
You need to write a function able to determine the relative path from its
|
||||
containing binary to the installation root at runtime.\\
|
||||
|
||||
\begin{itemize}
|
||||
\item No need to hardcode resouce location in the sources
|
||||
\item Path to resources should be located based on their types, such as:\\
|
||||
{\code LIBRARY}, {\code BINARY}, {\code DATA}, {\code CONFIG},
|
||||
etc.
|
||||
\item Aware of the install tree directory structure
|
||||
\item Just make sure that install tree structure is not violated
|
||||
\end{itemize}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
|
@ -0,0 +1,45 @@
|
|||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Ninja" Generator, CMake Version 3.13
|
||||
|
||||
# This file contains all the rules used to get the outputs files
|
||||
# built from the input files.
|
||||
# It is included in the main 'build.ninja'.
|
||||
|
||||
# =============================================================================
|
||||
# Project: presentation
|
||||
# Configuration:
|
||||
# =============================================================================
|
||||
# =============================================================================
|
||||
|
||||
#############################################
|
||||
# Rule for running custom commands.
|
||||
|
||||
rule CUSTOM_COMMAND
|
||||
command = $COMMAND
|
||||
description = $DESC
|
||||
|
||||
|
||||
#############################################
|
||||
# Rule for re-running cmake.
|
||||
|
||||
rule RERUN_CMAKE
|
||||
command = /usr/bin/cmake -S/home/matteo/cmake-presentation -B/home/matteo/cmake-presentation
|
||||
description = Re-running CMake...
|
||||
generator = 1
|
||||
|
||||
|
||||
#############################################
|
||||
# Rule for cleaning all built files.
|
||||
|
||||
rule CLEAN
|
||||
command = /usr/bin/ninja -t clean
|
||||
description = Cleaning all built files...
|
||||
|
||||
|
||||
#############################################
|
||||
# Rule for printing all primary targets available.
|
||||
|
||||
rule HELP
|
||||
command = /usr/bin/ninja -t targets
|
||||
description = All primary targets available:
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
|
||||
\begin{frame}
|
||||
\frametitle{Starting from today}
|
||||
|
||||
\begin{center}
|
||||
\huge Things you can start doing\newline Right Now™
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Use targets in place of variables}
|
||||
|
||||
\begin{codebox}[minted options={fontsize=\scriptsize}]{CMake}{}
|
||||
find_package(GTest REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS system thread)
|
||||
find_package(EXPAT REQUIRED) # only vars
|
||||
|
||||
add_library(alexandria …)
|
||||
\end{codebox}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=targets1]{CMake}
|
||||
target_link_libraries(alexandria
|
||||
PRIVATE
|
||||
${BOOST_LIBRARIES}
|
||||
${EXPAT_LIBRARIES}
|
||||
${GTEST_MAIN_LIBRARIES})
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=targets1]{CMake}
|
||||
target_link_libraries(alexandria
|
||||
PRIVATE
|
||||
Boost::system
|
||||
Boost::thread
|
||||
GTest::Main
|
||||
${EXPAT_LIBRARIES}) # legacy
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Use target-specific commands\footnote{An exception is of
|
||||
course in toolchain files.}}
|
||||
|
||||
Some commands propagate to all subfolders and included files. This
|
||||
can lead to potential problems where some targets get extra
|
||||
unintended flags.
|
||||
|
||||
\vspace{.3em}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=tgtspecific1]{CMake}
|
||||
add_definitions(-DDEFINE_SOMETHING=1)
|
||||
add_compile_options(-fvisibility=hidden)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=tgtspecific1]{CMake}
|
||||
target_compile_definitions(tgt PRIVATE
|
||||
DEFINE_SOMETHING=1)
|
||||
target_compile_options(tgt PRIVATE
|
||||
"-fno-tree-vrp")
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Avoid \texttt{target\_include\_directories}}
|
||||
|
||||
\begin{codebox}[minted options={fontsize=\scriptsize}]{CMake}{}
|
||||
find_package(EXPAT REQUIRED) # external, has only vars
|
||||
find_package(Boost REQUIRED) # external, has targets
|
||||
add_library(alexandria egypt.cc)
|
||||
target_link_libraries(alexandria
|
||||
PUBLIC calliope clio Boost::filesystem
|
||||
PRIVATE euterpe erato ${EXPAT_LIBRARIES})
|
||||
\end{codebox}
|
||||
|
||||
\vspace{.2em}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=tgtincdir1]{CMake}
|
||||
target_include_directories(alexandria
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}/include
|
||||
$<TARGET_PROPERTY:calliope,#
|
||||
INTERFACE_INCLUDE_DIRECTORIES>
|
||||
PRIVATE ${EUTERPE_INCLUDE_DIRS} # ...
|
||||
${CMAKE_SOURCE_DIR}/calliope/inc
|
||||
${BOOST_INCLUDE_DIRS}
|
||||
${EXPAT_INCLUDE_DIRS})
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=tgtincdir1]{CMake}
|
||||
target_include_directories(alexandria
|
||||
PUBLIC $<BUILD_INTERFACE:#
|
||||
${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:#
|
||||
${include_install_rel_dir}>
|
||||
PRIVATE ${EXPAT_INCLUDE_DIRS})
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Use PRIVATE and PUBLIC}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=privpub1]{CMake}
|
||||
target_link_libraries(tgt
|
||||
libA
|
||||
libB
|
||||
libC)
|
||||
|
||||
target_compile_definitions(tgt
|
||||
HAVE_THINGIE)
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=privpub1]{CMake}
|
||||
target_link_libraries(tgt
|
||||
PRIVATE libA
|
||||
libB
|
||||
PUBLIC libC)
|
||||
|
||||
target_compile_definitions(tgt
|
||||
PRIVATE HAVE_THINGIE)
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Prefer feature checks}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=feat1]{CMake}
|
||||
if(APPLE OR IOS OR (UNIX AND NOT ANDROID))
|
||||
target_compile_definitions(lua PRIVATE
|
||||
HAVE_POSIX_SPAWN)
|
||||
endif()
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=feat1]{CMake}
|
||||
check_symbol_exists("posix_spawn" "spawn.h"
|
||||
has_posix_spawn)
|
||||
if(has_posix_spawn)
|
||||
target_compile_definitions(lua PRIVATE
|
||||
HAVE_POSIX_SPAWN)
|
||||
endif()
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Make your package relocatable}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{badcodebox}[equal height group=relocatable1]{CMake}
|
||||
install(FILES "example.conf"
|
||||
DESTINATION some/strange/folder)
|
||||
\end{badcodebox}
|
||||
|
||||
\begin{badcodebox}[equal height group=relocatable2]{C++}
|
||||
char buf[2048];
|
||||
getcwd(buf, 2048);
|
||||
|
||||
using boost::filesystem::path;
|
||||
path rez = path(buf) /
|
||||
HARDCODED_ABSOLUTE_PREFIX_PATH
|
||||
/ "some" / "strange" / "folder" /
|
||||
"example.conf";
|
||||
\end{badcodebox}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{.5\textwidth}
|
||||
\begin{goodcodebox}[equal height group=relocatable1]{CMake}
|
||||
include(GNUInstallDirs)
|
||||
install(RESOURCES "example.conf"
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_SYSCONFDIR}/appname)
|
||||
\end{goodcodebox}
|
||||
|
||||
\begin{goodcodebox}[equal height group=relocatable2]{C++}
|
||||
using your_ns::some_enum::ResourceType;
|
||||
|
||||
using boost::filesystem::path;
|
||||
path = your_ns::get_resource_path(
|
||||
ResourceType::CONFIG,
|
||||
{ "appname", "example.conf" });
|
||||
\end{goodcodebox}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------
|
|
@ -0,0 +1,20 @@
|
|||
\subsection{Troubleshooting}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Troubleshooting}
|
||||
When problems arise while hacking CMake code, do \textbf{not} panic!
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
Run in the build directory:\\
|
||||
\texttt{\$ cmake --trace-expand . 2> trace\_expand.txt}.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
This will give more insight about what happens behind the scenes.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
\subsection{The CMake processing steps}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Projects and targets}
|
||||
|
||||
\begin{center}
|
||||
\huge Defining what to build
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{The CMake Process}
|
||||
|
||||
\begin{columns}
|
||||
\begin{column}{0.425\textwidth}
|
||||
CMake has two main steps:
|
||||
\begin{itemize}
|
||||
\item Configure step.
|
||||
\item Generate step.
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
|
||||
\begin{column}{0.575\textwidth}
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=.8\textwidth,keepaspectratio]{images/cmake-simple-flowchart.png}
|
||||
\caption*{\tiny 2017 © Jeff Preshing \url{http://preshing.com/20170511/how-to-build-a-cmake-based-project/}}
|
||||
\end{figure}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{$1^{st}$ step - Configuration}
|
||||
|
||||
In the \emph{configure} step CMake processes all the input given to
|
||||
it, via \texttt{CMakeLists.txt}, and creates an internal
|
||||
representation of the build to be performed. \texttt{CMakeCache.txt}
|
||||
is generated at this step.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The end of this step is expressed by \texttt{"Configuring done"}
|
||||
message from CMake.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{$2^{nd}$ step - Generation}
|
||||
|
||||
In the \emph{generate} step CMake will produce native build tool
|
||||
files e.g. Visual Studio solution files, XCode project files, Ninja
|
||||
build files etc.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The end of this step is expressed by \texttt{"Generating done"}
|
||||
message from CMake.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{About targets}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Targets and dependency propagation}
|
||||
|
||||
\begin{center}
|
||||
\huge Targets and their dependencies
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Targets}
|
||||
|
||||
A CMake-based buildsystem is organized as a set of high-level
|
||||
logical \emph{targets}.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
Each target corresponds to an executable or library, or is a custom
|
||||
target containing custom commands.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
add_library(archive archive.cpp zip.cpp lzma.cpp)
|
||||
add_executable(zipapp zipapp.cpp)
|
||||
target_link_libraries(zipapp archive)
|
||||
\end{codebox}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Transitive Usage Requirements}
|
||||
|
||||
The usage requirements of a target can transitively propagate to
|
||||
dependents.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The {\code{target\_link\_libraries()}} command has
|
||||
\texttt{PRIVATE}, \texttt{INTERFACE}, and \texttt{PUBLIC} keywords
|
||||
to control the propagation.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Transitive Usage Requirements}
|
||||
|
||||
A dependency should be specified in a use of
|
||||
{\code{target\_link\_libraries()}} with the:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{PRIVATE} keyword, if it is used \emph{only} by the
|
||||
implementation of a library, and not in its public header files.
|
||||
\item \texttt{PUBLIC} keyword, if a dependency is additionally
|
||||
used in the header files of a library (e.g. any header
|
||||
inclusion).
|
||||
\item \texttt{INTERFACE} keyword, if is \emph{not} used by the
|
||||
implementation of a library, but only by its public header
|
||||
files.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Transitive Usage Requirements – Example}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
add_library(liba a.cpp)
|
||||
target_compile_definitions(liba INTERFACE USING_LIB_A)
|
||||
|
||||
add_library(libb b.cpp)
|
||||
target_compile_definitions(libb INTERFACE USING_LIB_B)
|
||||
|
||||
add_library(libc c.cpp)
|
||||
target_link_libraries(libc PUBLIC liba PRIVATE libb)
|
||||
# libc is compiled with -DUSING_LIB_A and -DUSING_LIB_B
|
||||
|
||||
add_executable(app main.cpp)
|
||||
target_link_libraries(app libc)
|
||||
# app is compiled with -DUSING_LIB_A
|
||||
\end{codebox}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Targets – Modifier functions}
|
||||
|
||||
You should use the following functions to control your targets:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\code{target\_include\_directories()}} – adds directories to
|
||||
the include search path.
|
||||
\item {\code{target\_compile\_definitions()}} – adds pre-processor
|
||||
definitions.
|
||||
\item {\code{target\_compile\_options()}} – adds compiler options
|
||||
(\texttt{-Wall, /bigobj}).
|
||||
\item {\code{target\_compile\_features()}} – adds necessary compiler
|
||||
features (\texttt{cxx\_constexpr, cxx\_variadic\_templates}).
|
||||
\item {\code{target\_sources()}} – adds more source files to the
|
||||
target.
|
||||
\item {\code{target\_link\_libraries()}} – add library dependency.
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\subsection{Preparing for packaging}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Locating packages}
|
||||
|
||||
\begin{center}
|
||||
\huge Preparing the project for packaging
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{CMake packages}
|
||||
Packages provide dependency information to CMake.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
Packages are found with the {\code{find\_package()}} command.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The result of using {\code{find\_package()}} is either a set of
|
||||
\texttt{IMPORTED} targets, or a set of variables
|
||||
e.g. \texttt{<package>\_FOUND}, \texttt{<package>\_INCLUDE\_DIRS},
|
||||
\texttt{<package>\_LIBRARIES}.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Packages – Example}
|
||||
CMake provides direct support for two forms of packages:
|
||||
\begin{itemize}
|
||||
\item \texttt{CONFIG}-file packages (the new way).
|
||||
\item Find-\texttt{MODULE} packages (prioritized for backwards-compat).
|
||||
\end{itemize}
|
||||
|
||||
\begin{codebox}{CMake}{}
|
||||
# CMake provides a Boost find-module
|
||||
find_package(Boost 1.60.0 MODULE REQUIRED)
|
||||
|
||||
# Qt Project provides a Qt5 package config file.
|
||||
find_package(Qt5Core 5.9.0 CONFIG REQUIRED
|
||||
COMPONENTS Widgets)
|
||||
|
||||
# Use pkg-config via the LibXml2 find-module
|
||||
find_package(LibXml2 MODULE REQUIRED)
|
||||
\end{codebox}
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Packages – Config-file}
|
||||
|
||||
A config-file package the recommended CMake package type.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The config-file package consists of a set of files provided by
|
||||
upstreams for downstreams to use.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The Qt Project doesn't use CMake as their own build system, but
|
||||
they do provide a config-file package for CMake users.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Packages -- Find-module}
|
||||
|
||||
A find-module is needed when the upstream is not built with CMake,
|
||||
or is not CMake-aware enough to otherwise provide a package
|
||||
configuration file.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The find-module is a file with a set of rules for finding the
|
||||
required pieces of a dependency, primarily header files and
|
||||
libraries e.g. \texttt{FindBoost.cmake}.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
||||
|
||||
\begin{frame}[containsverbatim]
|
||||
\frametitle{Packages – Config-file continued}
|
||||
|
||||
A config-file package can be used in two ways:
|
||||
\begin{itemize}
|
||||
\item to find a configured project that is already part of the
|
||||
build.
|
||||
\item to import an installed package.
|
||||
\end{itemize}
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
The process of creating a config-file package using CMake commands
|
||||
({\code{configure\_package\_config\_file()}},
|
||||
{\code{write\_basic\_package\_version\_file()}}, {\code{install()}},
|
||||
{\code{export()}}) is quite verbose, and error prone.
|
||||
\end{frame}
|
||||
|
||||
% --------------------------------------------------------------------
|
Loading…
Reference in New Issue