Linux'taki bir projeden CMake kullanarak Visual Studio 2012 projesi üretirken aldığım notlar aşağıda. Dizinin şöyle bir yapıda olduğunu
. En üstteki CMakeLists.txt mi yoksa bu yapı mı daha iyi emin değilim.
1. "Browse Source" ile kaynak kodun bulunduğu dizin seçilir. Kaynak kod dizininde CMakeLists.txt dosyası da bulunmalı
2. "Browse Build" ile .sln dosyasının nerede oluşturulacağı seçilir.
3. "Configure" ile generator seçilir. Örneğin Visual Studio 11 seçilir.
4. "Generate" düğmesi ile .sln oluşturulur
yazısına taşıdım.
Metodlar
cmake programlama diliyle o kadar fazla sayıda metod geliyor ki hepsini anlamak ve bilmek kolay değil. Kullandığım bazı metodlar şöyle. Büyük küçük fark etmiyor
cmake sürümü
İstersek en düşük cmake sürümünü belirtebiliriz. Şöyle
yaparız.
CMAKE_MINIMUM_REQUIRED(VERSION 3.4.1)
project
Projenin adını belirtiriz. Aşağıdaki komut projenin adını atar. MyProject.sln dosyasını oluşturur
PROJECT( MyProject )
file
Sonra Projede kullanılan dosya isimleri belirlenir.
Örnek
Dosya isimleri mylist adlı listeye doldurmak için şöyle
yaparız
file(GLOB_RECURSE mylist "./*.cpp" "./*.h")
Örnek
Öz yinelemeli olmasın istersek şöyle
yaparız. Bu sefer SOURCE adlı listeye doldurulur.
file(GLOB SOURCES *.cpp)
Örnek
Bazı projeler dosya tiplerine göre listeler
oluşturuyor. Bence gereksiz bir hareket.
file(GLOB_RECURSE CXX_SRCS src/*.cpp)
file(GLOB_RECURSE C_SRCS src/*.c)
file(GLOB_RECURSE HPP_HDRS src/*.hpp)
file(GLOB_RECURSE H_HDRS src/*.h)
Örnek
Dosyalar projeye eklenir. Şöyle
yaparız.
# Configure source files for production code
file(GLOB SOURCES ../../sources/*.cpp)
# Tell the cmake what needs to be builded
add_executable( myProject ${SOURCES} )
find package
Belirtilen kütüphanalerin (.so veya .lib) kurulu olduğunu kontrol eder. Boost için şöyle
yaparız.
FIND_PACKAGE(Boost 1.59.0 REQUIRED COMPONENTS system thread filesystem)
Çıktı olarak şunu
görürüz.
-- Boost version: 1.59.0
-- Found the following Boost libraries:
-- system
-- thread
-- filesystem
Eğer sadece belli bir paketin kurulu olduğunu kontrol etmek istersek şöyle
yaparız. Bu durum örneğin header only bir kütüphaneyi kullanacaksak işe yarar.
find_package(Boost REQUIRED)
İstersek sürüm numarası da
verebiliriz.
find_package(Boost 1.58.0 REQUIRED)
add_compile_options
Şöyle yaparız. Eğer belli bir hedef için kullanmak istersek target_compile_options() ta kullanılabilir.
add_compile_options(-fno-rtti)
add_custom_command
Örnek
Şöyle
yaparız.
add_custom_command(TARGET MyProject
POST_BUILD
COMMAND cp foo.h ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
Örnek
Visual Studio'da build sonrasında bazı kopyalama işlemleri için post build copy komutu şöyle
yaparız.
ADD_CUSTOM_COMMAND(TARGET MyProject
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/*.ini ${PROJECT_BINARY_DIR}
)
add_custom_target
Çağırmak için şöyle
yaparız.
cmake --build /path/to/build/directory --target copy_all
Şöyle
yaparız.
add_custom_target (copy_all
COMMAND ${CMAKE_SOURCE_DIR}/copy.sh ${files}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
add_definitions
Açıklaması
şöyle. Bu komut ile add_compile_options() hep karışıyor. add_definitions() preprocessor için, diğeri ise derleyiciye seçenek geçmek için.
add_definitions is meant to add preprocessor definitions.
Eğer lazımsa -D ile başlayan preprocessor seçeneklerini belirlenir.
ADD_DEFINITIONS(-D_WIN32_WINNT=0X600)
Şöyle
yaparız.
add_definitions(-DBOOST_LOG_DYN_LINK)
add_executable
Kaynak kodlar bir set içinde toplanır. Sonra verilen kaynak kodları derlemek ve bir uygulama üretmek için şöyle
yaparız.
set(SOURCES
src/p2.c
src/p1.h
src/p1.c)
add_executable(myexe ${SOURCES})
Set'i oluşturmak için glob
yapılabilir.
file(GLOB_RECURSE CXX_SRCS src/*.cpp)
file(GLOB_RECURSE C_SRCS src/*.c)
file(GLOB_RECURSE HPP_HDRS src/*.hpp)
file(GLOB_RECURSE H_HDRS src/*.h)
set(SRCS "${C_SRCS};${CXX_SRCS}")
set(HDRS "${H_HDRS};${HPP_HDRS}")
add_executable(monoRenderer ${SRCS} ${HDRS})
Eğer istersek kaynak dosyaları teker teker de elle
yazabiliriz.
ADD_EXECUTABLE(myexe src/mangaMe.cpp)
add_library
CMake add_library yazısına taşıdım.
add_subdirectory
İki tane CMakeLists.txt dosyası olsun
CMakeLists.txt
src/
CMakeLists.txt
main.cpp
build/
src içindeki ikinci CMakeLists.txt dosyasının tetiklenmesi için şöyle
yaparız.
#tell CMake that we have some source files located in the src directory
add_subdirectory(src)
include
Bir başka CMake dosyasını dahil etmek için kullanılır. Dahil edilen CMake içindeki metodlar da çağrılabilir. Şöyle
yaparız.
# Conan setup
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
include_directories
Şöyle
yaparız. Bu komut birden fazla kere çağrılabilir.
INCLUDE_DIRECTORIES(includes)
Bir değişkene atanan değeri kullanmak için şöyle
yaparız.
set(BOOST_ROOT "C:/dev/tools/boost_1_60_0")
include_directories(${INCLUDE_DIRECTORIES} ${BOOST_ROOT} include)
install - Target
Şöyle
yaparız.
install(TARGETS helloworld
RUNTIME DESTINATION ../build)
install - Custom
Söz dizimi
şöyle
install([[SCRIPT <file>] [CODE <code>]]
[COMPONENT <component>] [...])
Açıklaması
şöyle
The SCRIPT form will invoke the given CMake script files during installation. If the script file name is a relative path it will be interpreted with respect to the current source directory. The CODE form will invoke the given CMake code during installation. Code is specified as a single argument inside a double-quoted string.
Code içinde mesaj vermek için şöyle
yaparız.
install(CODE "MESSAGE(\"Sample install message.\")")
Code içinde script çalıştırmak için şöyle
yaparız.
install(CODE "execute_process(COMMAND my_script.sh)")
set
Bir değişkene değer atar. Böylece değişken cmake içinde kullanılabilir. Şöyle
yaparız.
SET(BOOST_DIR $ENV{PATH})
Derleyici sürümü seçmek için
CMAKE_CXX_FLAGS yazısına bakınız.
set_target_properties
Bazı warningleri şöyle kapatmak için şöyle
yaparız.
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd4819")
Derleyici sürümü seçmek için şöyle
yaparız.
add_executable(Randomshitprogram ${SOURCE_FILES})
set_target_properties(Randomshitprogram
PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
)
Çıktı dosya ismini değiştirmek için şöyle
yaparız.
# Adds 'd' onto artifacts - does NOT apply to executables.
# For executables, this needs to be done an exec-by-exec
# basis.
set(CMAKE_DEBUG_POSTFIX "d")
# Add postfix onto executable debug filename
set_target_properties(myapp PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_compile_options
Şöyle
yaparız.
target_compile_options(foo PUBLIC -fno-rtti)
target_link_libraries
Target'ımız ile linklemek istediğimiz lib isimlerini yazarız. Açıklaması
şöyle
target_link_libraries works on targets created with add_library and add_executable.
Şöyle
yaparız. Bu komut birden fazla kere çağrılabilir.
target_link_libraries(wpcaplib.lib)
WriteCompilerDetectionHeader
Şöyle
yaparız.
include(WriteCompilerDetectionHeader)
write_compiler_detection_header(
FILE foo_compiler_detection.h
PREFIX foo
COMPILERS GNU
FEATURES cxx_attribute_deprecated
)
CMake Değişkenleri
Değişlenlerin sayısı oldukça fazla. Değişkenler
şöyle.
Hazır Macrolar
CMAKE_SYSTEM_NAME
CMake System Variables yazısına taşıdım.
Dizinlerle İlgili Hazır Macrolar
PROJECT_SOURCE_DIR
CMakeLists.txt dosyasının bulunduğu dizin
CMAKE_BINARY_DIR
Çıktının konulacağı dizin. Visual Studio için .sln dosyasının oluşturulacağı yer.
CMAKE_CURRENT_SOURCE_DIR
Tam ne işe yaradığını
anlamadım.
Derleyiciyle İlgili Hazır Macrolar
CMAKE_ARCHIVE_OUTPUT_DIRECTORY
Statitic kütüphanenin nerede oluşturulacağını belirtir. Şöyle
yaparız.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
CMAKE_BUILD_TYPE
Şöyle
yaparız.
set(CMAKE_BUILD_TYPE Release)
CMAKE_COMPILER_IS_GNUCC
Şöyle
yaparız.
if (WIN32)
if (CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--stack,4194304 -fpermissive")
elseif(MSVC)
# add options for Visual C/C++ Compiler here
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /F 4194304")
endif()
endif()
CMAKE_CXX_COMPILER
Derleyicinin ismini şöyle
öğreniriz.
cmake_minimum_required (VERSION 2.8.11)
MESSAGE( STATUS "Compiler: " ${CMAKE_CXX_COMPILER} )
Çıktı olarak şunu
alırız.
-- Compiler: /usr/bin/c++
Generator Expression
If/Else gibi düşünülebilir. Bir sonuç dönerler. İki noktanın solundaki değişken sağdaki değere eşitse ikinci ifade 'nin değeri dönülür. Eğer Config değişkeni Debug ise sonuç Release'dir., Config değişkeni Debug değilse boş string
döner.
$<$<CONFIG:Debug>:Release>
Filtre
Visual Studio, Eclipse gibi dosya sistemi ile çalışmıyor. Kendi dosya/filtre sistemi var. Bu filtre sistemin dosya yolları ile aynı olacak şekilde üretmek için şöyle
yaptım.
macro(GroupSources curdir)
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach(child ${children})
if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
GroupSources(${curdir}/${child})
else()
string(REPLACE "/" "\\" groupname ${curdir})
# I would like to call the src root folder in a different name, only in visual studio (not mandatory requirement)
string(REPLACE "src" "Common" groupname ${groupname})
source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
endforeach()
endmacro()
# Execute the macro
GroupSources(src)