3.5. Project declaration¶
Next must-have command is
project.
Command project(foo)
will set languages to C and C++ (default),
declare some foo_*
variables and run basic build tool checks.
CMake documentation
3.5.1. Tools discovering¶
By default on calling project
command CMake will try to detect compilers
for default languages: C and C++. Let’s add some variables and check where
they are defined:
cmake_minimum_required(VERSION 2.8)
message("Before 'project':")
message(" C: '${CMAKE_C_COMPILER}'")
message(" C++: '${CMAKE_CXX_COMPILER}'")
project(Foo)
message("After 'project':")
message(" C: '${CMAKE_C_COMPILER}'")
message(" C++: '${CMAKE_CXX_COMPILER}'")
Examples on GitHub
Run test on Linux
:
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hset-compiler -B_builds
Before 'project':
C: ''
C++: ''
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
After 'project':
C: '/usr/bin/cc'
C++: '/usr/bin/c++'
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
CMake will run tests for other tools as well, so try to avoid
checking of anything before project
, place all checks
after project declared.
Also project
is a place where toolchain file will be read.
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
message("Before 'project'")
project(Foo)
message("After 'project'")
# toolchain.cmake
message("Processing toolchain")
[project-examples]> rm -rf _builds
[project-examples]> cmake -Htoolchain -B_builds -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
Before 'project'
Processing toolchain
Processing toolchain
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
Processing toolchain
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
Processing toolchain
-- Detecting C compiler ABI info - done
-- Detecting C compile features
Processing toolchain
Processing toolchain
Processing toolchain
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
Processing toolchain
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
Processing toolchain
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
Processing toolchain
Processing toolchain
Processing toolchain
-- Detecting CXX compile features - done
After 'project'
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
Note
You may notice that toolchain read several times
3.5.2. Languages¶
If you don’t have or don’t need support for one of the default languages you can set language explicitly after name of the project. This is how to setup C-only project:
cmake_minimum_required(VERSION 2.8)
message("Before 'project':")
message(" C: '${CMAKE_C_COMPILER}'")
message(" C++: '${CMAKE_CXX_COMPILER}'")
project(Foo C)
message("After 'project':")
message(" C: '${CMAKE_C_COMPILER}'")
message(" C++: '${CMAKE_CXX_COMPILER}'")
There is no checks for C++ compiler and variable with path to C++ compiler is empty now:
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hc-compiler -B_builds
Before 'project':
C: ''
C++: ''
-- The C compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
After 'project':
C: '/usr/bin/cc'
C++: ''
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
Of course you will not be able to build C++ targets anymore. Since CMake
thinks that *.cpp
extension is for C++ sources (by default) there will
be error reported if C++ is not listed (discovering of C++
tools will not be triggered):
cmake_minimum_required(VERSION 2.8)
project(Foo C)
add_library(foo foo.cpp)
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hcpp-not-found -B_builds
-- The C compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
CMake Error: Cannot determine link language for target "foo".
CMake Error: CMake can not determine linker language for target: foo
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
We can save some time by using special language NONE
when we don’t need any
tools at all:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
No checks for C or C++ compiler as you can see:
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hno-language -B_builds
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
Note
Such form will be used widely in examples in cases when we don’t need to build targets.
Note
For CMake 3.0+ sub-option LANGUAGES
added, since it will be:
cmake_minimum_required(VERSION 3.0)
project(foo LANGUAGES NONE)
3.5.3. Variables¶
Command project
declare *_{SOURCE,BINARY}_DIR
variables. Since version
3.0
you can add VERSION
which additionally declare
*_VERSION_{MAJOR,MINOR,PATCH,TWEAK}
variables:
cmake_minimum_required(VERSION 3.0)
message("Before project:")
message(" Source: ${PROJECT_SOURCE_DIR}")
message(" Binary: ${PROJECT_BINARY_DIR}")
message(" Version: ${PROJECT_VERSION}")
message(" Version (alt): ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
project(Foo VERSION 1.2.7)
message("After project:")
message(" Source: ${PROJECT_SOURCE_DIR}")
message(" Binary: ${PROJECT_BINARY_DIR}")
message(" Version: ${PROJECT_VERSION}")
message(" Version (alt): ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hvariables -B_builds
Before project:
Source:
Binary:
Version:
Version (alt): ..
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
After project:
Source: /.../project-examples/variables
Binary: /.../project-examples/_builds
Version: 1.2.7
Version (alt): 1.2.7
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
You can use alternative foo_{SOURCE,BINARY}_DIRS
/
foo_VERSION_{MINOR,MAJOR,PATCH}
synonyms. This is useful
when you have hierarchy of projects:
# Top level CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(foo)
message("From top level:")
message(" Source (general): ${PROJECT_SOURCE_DIR}")
message(" Source (foo): ${foo_SOURCE_DIR}")
add_subdirectory(boo)
# CMakeLists.txt from 'boo' directory
cmake_minimum_required(VERSION 2.8)
project(boo)
message("From subdirectory 'boo':")
message(" Source (general): ${PROJECT_SOURCE_DIR}")
message(" Source (foo): ${foo_SOURCE_DIR}")
message(" Source (boo): ${boo_SOURCE_DIR}")
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hhierarchy -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
From top level:
Source (general): /.../project-examples/hierarchy
Source (foo): /.../project-examples/hierarchy
From subdirectory 'boo':
Source (general): /.../project-examples/hierarchy/boo
Source (foo): /.../project-examples/hierarchy
Source (boo): /.../project-examples/hierarchy/boo
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
As you can see we are still able to use foo_*
variables even if new
command project(boo)
called.
3.5.4. When not declared¶
CMake will implicitly declare project
in case there is no such command
in top-level CMakeLists.txt. This will be equal to calling project
before any other commands. It means that project
will be called before
cmake_minimum_required
so can lead to problems described in
previous section:
# Top level CMakeLists.txt
message("Before 'cmake_minimum_required'")
cmake_minimum_required(VERSION 2.8)
add_subdirectory(boo)
# CMakeLists.txt in directory 'boo'
cmake_minimum_required(VERSION 2.8)
project(boo)
[project-examples]> rm -rf _builds
[project-examples]> cmake -Hnot-declared -B_builds
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Before 'cmake_minimum_required'
-- Configuring done
-- Generating done
-- Build files have been written to: /.../project-examples/_builds
3.5.5. Summary¶
You must have
project
command in your top-levelCMakeLists.txt
Use
project
to declare non divisible monolithic hierarchy of targetsTry to minimize the number of instructions before
project
and verify that variables are declared in such block of CMake code