ttroy50 / cmake-examples Goto Github PK
View Code? Open in Web Editor NEWUseful CMake Examples
Home Page: http://ttroy50.github.io/cmake-examples
License: MIT License
Useful CMake Examples
Home Page: http://ttroy50.github.io/cmake-examples
License: MIT License
Hi,
In your example "cmake-examples/01-basic/D-shared-library/", what happens when we call main? Where does it look for the library? Can we define it somehow? When we package the software, is putting the library in the same folder as main enough?
Thank you for the examples,
This is just a request for adding examples using cmake-presets.
Thanks for your work.
Hey there,
I was going through the examples to learn about cmake & i saw that for shared library examples if we are building the executable it will show following
D:\Study\compiler\software\src\Hello.cpp(3): fatal error C1083: Cannot open include file: 'shared/Hello.h': No such fil
e or directory [D:\Study\compiler\software\build\hello_library.vcxproj]
I am beginning to dive into Cmake and this repository contains plenty of helpful examples. Lines of code target specifically Linux OS'. Shouldn't be all code cross-platform oriented, since Cmake itself is fundamentally cross-platform oriented?
P.S.: A noob.
Demo issue text
Hello,
Are there plans to add code coverage examples using llvm-cov
(clang) and lcov
(gcc)?
If not, it is my proposal :)
In 01-basic\H-third-party-library, the example project uses find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)
to find the third-party-library Boost, but without using include_directories(${Boost_INCLUDE_DIRS})
, how can the target find where the "XXX.h" files are?
And in the file README.adoc, in Checking if the package is found
part, the example uses include_directories(${Boost_INCLUDE_DIRS})
if(Boost_FOUND)
message ("boost found")
include_directories(${Boost_INCLUDE_DIRS})
else()
message (FATAL_ERROR "Cannot find Boost")
endif()
In fact, without writing include_directories(${Boost_INCLUDE_DIRS})
, the example project can compile and run without any problems, but it really confuse me whether I need to use include_directories(${XXX_INCLUDE_DIRS})
after using find_package(XXX)
and why or why not.
The headings and toc aren't always correct or consistent. To make this better headings should always use the "#" syntax to specify level
Hello, nice work creating/collecting all the examples.
I used your project to integrate clang-format into CMake. Doing that I adapted it slightly and want to suggest this as a possible improvement.
I found that the check target would just error if code was not formatted. In clang-format you can use the --dry--run and --Werror flags to get output of what was not formatted and also getting a sensible return code without grep.
My code for the custom target looks like this:
add_custom_target(clang-format-check
COMMENT "Checking clang-format changes"
COMMAND ${ClangFormat_EXECUTABLE}
--style=file
--dry-run
--Werror
${ALL_SOURCE_FILES}
)
Some libraries like GLFW provide a global include file or files.
Taking the folder structure from the 01-basic/C-static-library
as a base, it would work like this:
$ tree
.
├── CMakeLists.txt
├── include
│ └── static
│ └── MyLib.h
└── src
├── Hello.h
├── Hello.cpp
└── main.cpp
Now all headers could live inside the source directory and a single MyLib.h
header could be provided for library users, with the definitions of everything that should be exposed.
This would be useful for writing internal classes that are not exposed to the library users, concentrating utilities in the "global header" (like GLFW does here, for example) while also providing library users with a single include file.
I have been trying to do this myself, but the problem I'm facing is getting the MyLib.h
file to resolve includes of files inside the src
folder. Given a few nudges in the right direction, I'd gladly submit a working example as a PR if this was to be considered a valid example.
Suppose I want to create a library which using Boost:
find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)
add_library(hello_library SHARED src/Hello.cpp)
target_include_directories(hello_library PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(hello_library PRIVATE Boost::filesystem)
May I ask what is the difference between
target_link_libraries(hello_library PRIVATE Boost::filesystem)
and
target_link_libraries(hello_library PUBLIC Boost::filesystem)
?
Just wanted to let you know that this link does not work.
By the way, awesome repo. Thanks.
Hi ttroy50, thanks for the tutorial, it has helped me very much. Well done! My personal project has a similar tree structure as your cmake-examples/02-sub-projects/A-basic/ with a couple of libraries and an app directory. The libraries I build with cmake 3.10.2 & make work very well, like yours do. However, my app binary does not. I have worked and worked on this... which is how I found my way to your ttroy50/cmake-examples.
The reason I am writing is because my error turns out to be the same as the cmake & make errors I encounter in your cmake-examples/02-sub-projects/A-basic/subbinary/CMakeLists.txt. Which is 'Target "subbinary" links to target "sub::lib1" but the target was not found. Perhaps a find_package() call is missing for an IMPORTED target, or an ALIAS target is missing?' etc etc
I was wondering if your /subbinary/CMakeLists.txt could be adjusted to clear these errors allowing it to generate a functional make on it. If so, I suspect it will teach me how to fix my own equivalent build problem.
Thanks and best regards from Rio del Mar, California. Billy
I have a question an cmake-examples/01-basic/H-third-party-library/
, we use find_package()
to find Boost CMake Module, and we need add Boost::filesystem
to CMakeLists.txt's target_link_libraries
, because our main.cpp has used this library. But our main.cpp also use boost::shared_ptr
, why we not add Boost::shared_ptr to the target_link_libraries
?
Your example solved my linking trouble. Thank you!
Please add examples for packaging using vcpkg similar to conan under package-management.
in https://github.com/ttroy50/cmake-examples/tree/master/01-basic/G-compile-flags:
the picture link(https://github.com/ttroy50/cmake-examples/blob/master/01-basic/G-compile-flags/cmake-gui-set-cxx-flag.png
) is not available
I use vscode to open and run the demo, but I get the error:
[main] Building folder: A-hello-cmake [proc] Executing command: "C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.07\bin\arm-none-eabi-gcc.exe" -v [main] Configuring folder: A-hello-cmake [proc] Executing command: "D:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_C_COMPILER:FILEPATH=C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.07\bin\arm-none-eabi-gcc.exe" "-DCMAKE_CXX_COMPILER:FILEPATH=C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.07\bin\arm-none-eabi-g++.exe" -Se:/Work/Test/A-hello-cmake -Be:/Work/Test/A-hello-cmake/build -G Ninja [cmake] Not searching for unused variables given on the command line. [cmake] -- The C compiler identification is GNU 10.3.1 [cmake] -- The CXX compiler identification is GNU 10.3.1 [cmake] -- Detecting C compiler ABI info [cmake] -- Detecting C compiler ABI info - failed [cmake] -- Check for working C compiler: C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.07/bin/arm-none-eabi-gcc.exe [cmake] -- Check for working C compiler: C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.07/bin/arm-none-eabi-gcc.exe - broken [cmake] CMake Error at D:/Program Files/CMake/share/cmake-3.21/Modules/CMakeTestCCompiler.cmake:69 (message): [cmake] The C compiler [cmake] [cmake] "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.07/bin/arm-none-eabi-gcc.exe" [cmake] [cmake] is not able to compile a simple test program. [cmake] [cmake] It fails with the following output: [cmake] [cmake] Change Dir: E:/Work/Test/A-hello-cmake/build/CMakeFiles/CMakeTmp [cmake] [cmake] Run Build Command(s):D:/Program Files (x86)/Python38-32/Scripts/ninja.exe cmTC_8197f && [1/2] Building C object CMakeFiles/cmTC_8197f.dir/testCCompiler.c.obj [cmake] [2/2] Linking C executable cmTC_8197f.exe [cmake] FAILED: cmTC_8197f.exe [cmake] cmd.exe /C "cd . && C:\PROGRA~2\GNUARM~1\102021~1.07\bin\AR19DD~1.EXE CMakeFiles/cmTC_8197f.dir/testCCompiler.c.obj -o cmTC_8197f.exe -Wl,--out-implib,libcmTC_8197f.dll.a -Wl,--major-image-version,0,--minor-image-version,0 && cd ." [cmake] c:/progra~2/gnuarm~1/102021~1.07/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: unrecognized option '--major-image-version' [cmake] c:/progra~2/gnuarm~1/102021~1.07/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: use the --help option for usage information [cmake] collect2.exe: error: ld returned 1 exit status [cmake] ninja: build stopped: subcommand failed. [cmake] [cmake] [cmake] [cmake] [cmake] [cmake] CMake will not be able to correctly generate this project. [cmake] Call Stack (most recent call first): [cmake] CMakeLists.txt:7 (project) [cmake] [cmake] [cmake] -- Configuring incomplete, errors occurred! [cmake] See also "E:/Work/Test/A-hello-cmake/build/CMakeFiles/CMakeOutput.log". [cmake] See also "E:/Work/Test/A-hello-cmake/build/CMakeFiles/CMakeError.log".
In the bottom of document 01-basic/F-build-type/README.adoc, the command running history is copied for a second unnecessary time.
Travis-ci examples should be added for all examples.
Currently only available for the first test
Current best practices in CMake are to define each target's include, link, and compile definitions on the target itself, using appropriate PRIVATE, PUBLIC, and INTERFACE annotations to define target usage requirements. This avoids issues caused by using 'global' configuration and enables automatic, transitive propagation of usage requirements.
This does depend on updates made in recent versions of CMake. I believe 2.8 is the earliest to support this, with further improvements in 3.x versions.
We should be able to test with different cmake versions to confirm that the examples work on them. This would also allow showing newer features like those raised in #5
@ttroy50, thanks much for your great examples.
I have tried to run them under Ubuntu 18.04 and it breaks on scan-build-3.6, since I have a newer clang version and I don't want to install clang-3.6
Is it any reason to keep this particular version?
It works fine with a stock Ubuntu 18.04 clang as well.
If you like I could provide a patch for it.
So much for building OpenCL. More straight out of the box errors, never could get it built, gave up. I can't understand how this entire build software is full of so many poorly written build files. Half of them don't even have the first line required in EVERY build which is the minimum version required. This one is no exception. Seriously. WTF?
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as
cmake_minimum_required(VERSION 3.27)
should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at /usr/share/cmake-3.27/Modules/WriteBasicConfigVersionFile.cmake:43 (message):
No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()
Call Stack (most recent call first):
/usr/share/cmake-3.27/Modules/CMakePackageConfigHelpers.cmake:239 (write_basic_config_version_file)
CMakeLists.txt:100 (write_basic_package_version_file)
CMake Error at /usr/share/cmake-3.27/Modules/CMakePackageConfigHelpers.cmake:239 (write_basic_config_version_file):
write_basic_config_version_file Function invoked with incorrect arguments
for function named: WRITE_BASIC_CONFIG_VERSION_FILE
Call Stack (most recent call first):
CMakeLists.txt:102 (write_basic_package_version_file)
CMake Error at /usr/share/cmake-3.27/Modules/CMakePackageConfigHelpers.cmake:239 (write_basic_config_version_file):
write_basic_config_version_file Function invoked with incorrect arguments
for function named: WRITE_BASIC_CONFIG_VERSION_FILE
Call Stack (most recent call first):
CMakeLists.txt:102 (write_basic_package_version_file)
CMake Error at CMakeLists.txt:105:
Parse error. Expected a command name, got unquoted argument with text
"${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/cmake/OpenCL${UTIL_LIB_NAME}/OpenCL${UTIL_LIB_NAME}ConfigVersion.cmake".
Is it possible to create a loadable kernel module example?
I know what the result of the Makefile should be
`obj-m += main.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean`
when I learn 01-basic/e-installing part, the compiler cl.exe find for **.lib not **.dll
and I google some resolutions for it below
set(cmake_windows_export_all_symbols on)
after writing that line, I can compile correctly.
so do those examples consider cross platform issues?
and thank you for this wonderful repository to us to learn CMake!
There is a step Adding Export Configuration (Step 11) in CMake Tutorial.
There seems no related examples about Export Configuration In the repository, could you add one?
as above
Well, as far as I know, the "target_compile_features" feature is now deprecated.
Where I found this issue
Building example 01-basic/D-shared-library on Visual Studio fails with the following error:
Build started...
1>------ Build started: Project: ZERO_CHECK, Configuration: Debug x64 ------
1>Checking Build System
2>------ Build started: Project: hello_library, Configuration: Debug x64 ------
2>Building Custom Rule D:/dev/cpp/cmake-examples/01-basic/D-shared-library/CMakeLists.txt
2>Hello.cpp
2>hello_library.vcxproj -> D:\Projets\Programmation\Cpp\cmake-examples\01-basic\D-shared-library\build\Debug\hello_library.dll
3>------ Build started: Project: hello_binary, Configuration: Debug x64 ------
3>Building Custom Rule D:/dev/cpp/cmake-examples/01-basic/D-shared-library/CMakeLists.txt
3>main.cpp
3>LINK : fatal error LNK1104: cannot open file 'Debug\hello_library.lib'
3>Done building project "hello_binary.vcxproj" -- FAILED.
4>------ Skipped Build: Project: ALL_BUILD, Configuration: Debug x64 ------
4>Project not selected to build for this solution configuration
========== Build: 2 succeeded, 1 failed, 0 up-to-date, 1 skipped ==========
This is because the shared library hello_library
does not exports any symbols. If a shared library does not export any symbols, Visual Studio will not create a *.lib file which is required by hello_binary
. On Windows, when building a shared library, you need to have __declspec(dllexport)
before every functions or classes that you want to export. When another project is using the compiled library, you need to have __declspec(dllimport)
.
CMake can be solve this problem in two different ways:
CMake 3.4 added the variable CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
. When set to true, it creates a pre-link event in Visual Studio to call cmake.exe which generates an exports.def
file that Visual Studio can use to exports most symbols.
To set this variable, you can add set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
to your CMakeLists.txt file or you can set the variable on the command line with -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE
.
This solution is not perfect. This flag does not translate to something in Visual Studio solution/project files. It allows you to export most of your code without changes. However, it fails to export global and static variables. You can read more about this in this blog post.
This option was also partially discussed in #52.
On Windows, this is the usual/expected way for creating a shared library.
If you add the following to CMakeLists.txt, you can generate an export file header:
include (GenerateExportHeader)
generate_export_header(hello_library)
This will generate the file called ${PROJECT_BINARY_DIR}/hello_library_export.h
which will declare the macro HELLO_LIBRARY_EXPORT
that resolves to __declspec(dllexport)
or __declspec(dllimport)
as appropriate. With CMake 3.22, the content will look like this: hello_library_export.h.txt.
All files that export symbols must include this generated header. For example, the file include/shared/Hello.h
must be modified as the following:
#include "hello_library_export.h"
class HELLO_LIBRARY_EXPORT Hello
Note the new include directive and the use of the HELLO_LIBRARY_EXPORT
macro before the class declaration.
To find this include file, the target hello_library
must be modified in CMakeLists.txt
with the following:
target_include_directories(hello_library
PUBLIC
${PROJECT_SOURCE_DIR}/include
${PROJECT_BINARY_DIR} # for hello_library_export.h
)
This is the expected way for creating a shared library. I do not have enough experience on Linux to know if gcc (or other compilers) will be able to understand/ignore __declspec(dllexport)
and __declspec(dllimport)
.
I am really happy to have found this tutorial. This is one of the most well made "step by step" guide I have seen. CMake lacks good and simple documentation and this repository really help. I am a huge fan of learning by examples. I also created a CMake guide myself.
Would you consider adding option 2 to the source code ? To clarify that this code is WINDOWS-ONLY, we could wrap the new code inside statements such as IF (WIN32)
in CMakeLists.txt and #ifdef __WIN32
in c++ header files.
I realize this would add more complexity to the example but I would argue that this guide should cover both Linux and Windows.
Syntax error in protodoc adoc
The examples are extremely practical and helpful, so I'll be referring a lot of people to this repository.
I think there are some conventions around unit test folders and files. If you could show some examples of how that would look with any unit test framework I think it would be sensible addition. Also, leveraging them with CTest would make sense if possible.
add_library(hello::library ALIAS hello_library)
why must to use alias name for hello_library? Can I not use the alias name?
It would be useful if there would be an example that includes multiple directory levels.
Example:
├── CMakeLists.txt
└── subfolder
└── CMakeLists.txt
└── subfolder1
│ └── CMakeLists.txt
└── subfolder2
└── CMakeLists.txt
I had a situation like that and manage to solve it. It would be nice to have a similar example (I did not manage to find one at least).
Extra Notes
Overriding the default install location
As mentioned the default install location is set from the CMAKE_INSTALL_PERFIX
, which defaults to /usr/local/
CMAKE_INSTALL_PERFIX
should CMAKE_INSTALL_PREFIX
i found some unnormal prints in this example. check it please.
# A CMake script to find all source files and setup clang-format targets for them
# Find all source files
set(CLANG_FORMAT_CXX_FILE_EXTENSIONS ${CLANG_FORMAT_CXX_FILE_EXTENSIONS} *.cpp *.h *.cxx *.hxx *.hpp *.cc *.ipp)
file(GLOB_RECURSE ALL_SOURCE_FILES ${CLANG_FORMAT_CXX_FILE_EXTENSIONS})
# Don't include some common build folders
set(CLANG_FORMAT_EXCLUDE_PATTERNS ${CLANG_FORMAT_EXCLUDE_PATTERNS} "/CMakeFiles/" "cmake")
# get all project files file
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
foreach (EXCLUDE_PATTERN ${CLANG_FORMAT_EXCLUDE_PATTERNS})
string(FIND ${SOURCE_FILE} ${EXCLUDE_PATTERN} EXCLUDE_FOUND)
if (NOT ${EXCLUDE_FOUND} EQUAL -1)
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
endif ()
endforeach ()
endforeach ()
message(STATUS "ALL_SOURCE_FILES: ${ALL_SOURCE_FILES}") # ${ALL_SOURCE_FILES} is empty
In the introduction when introducing the files for the example, they should be linked to instead of just named
when trying to run the text file the pop-up named PLEASE SELECT A VALID STARTUP ITEM is showing up and i couldnt run a file.
please help with the issue
here is my command and output:
❯ cmake -B ./build/ -DCMAKE_EXPORT_COMPILE_COMMANDS=on && sudo cmake --build build --target install
-- The C compiler identification is GNU 11.2.0
-- The CXX compiler identification is GNU 11.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/xxx/git/cmake-examples/01-basic/E-installing/build
[ 25%] Building CXX object CMakeFiles/cmake_examples_inst.dir/src/Hello.cpp.o
[ 50%] Linking CXX shared library libcmake_examples_inst.so
[ 50%] Built target cmake_examples_inst
[ 75%] Building CXX object CMakeFiles/cmake_examples_inst_bin.dir/src/main.cpp.o
[100%] Linking CXX executable cmake_examples_inst_bin
[100%] Built target cmake_examples_inst_bin
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/cmake_examples_inst_bin
-- Set runtime path of "/usr/local/bin/cmake_examples_inst_bin" to ""
-- Installing: /usr/local/lib/libcmake_examples_inst.so
-- Up-to-date: /usr/local/include
-- Up-to-date: /usr/local/include/installing
-- Up-to-date: /usr/local/include/installing/Hello.h
-- Up-to-date: /usr/local/etc/cmake-examples.conf
reopen the terminal and then run cmake_examples_inst_bin
gives following error:
cmake_examples_inst_bin: error while loading shared libraries: libcmake_examples_inst.so: cannot open shared object file: No such file or directory
output of ldd
:
ldd $(which cmake_examples_inst_bin)
linux-vdso.so.1 (0x00007ffe6751d000)
libcmake_examples_inst.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1713bc0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1713e00000)
I've been using FetchContent a lot recently, and it works pretty well. It would be good to provide an example of how it works for those learning. Also, it should include some of the content from the Integrating with find_package section of the manual.
There are a few cases that could be covered:
find_package
callsfind_package
calls when availableI suggest to update the default type section.
Instead of redefining the CMAKE_BUILD_TYPE variable, we can change the value using the associated property as follows
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY VALUE Release)
endif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
If one wishes to restrict choices to standard build types, it gives
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS None Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY VALUE Release)
endif(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.