CMake

  • 設定ファイル

  • CMakeLists.txt

  • 簡単な使い方

  • Visual Studio 2013でx64アーキテクチャ用のプロジェクトファイルを作成する.
    ビルド用の作業ツリーは, build_x64ディレクトリ以下に作成する.
    #cmake -G<generator name> <path-to-source>
    mkdir build_x64
    cd ./build_x64
    cmake -G"Visual Studio 12 2013 Win64" ..
    
    Visual Studioの場合デフォルトでは, ALL_BUILDとZERO_CHECKというプロジェクトが作成される.
    ALL_BUILD: make allに相当
    ZERO_CHECK: CMakeLists.txt更新されていた場合, プロジェクトファイルを更新する. cmakeコマンドを再実行する代わり.

  • CMake バージョンチェック

  • cmake_minimum_required(VERSION 3.5)
    

  • 変数定義

  • set(PROJECT_VERSION_MAJOR 0)
    set(PROJECT_VERSION_MINOR 1)
    set(PROJECT_VERSION_PATCH 0)
    set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
    
    #Print to console
    message(${PROJECT_VERSION})
    

  • プロジェクト名

  • set(ProjectName lcore)
    project(${ProjectName})
    

  • コンフィギュレーション

  • Visual StudioのようなマルチコンフィギュレーションなIDEの, コンフィギュレーションを設定.
    set(CMAKE_CONFIGURATION_TYPES "Debug" "Release")
    

  • コンフィギュレーションファイル

  • configure.inのようなもの.
    #configure.h.inに
    ##cmakedefine FOO_ENABLE
    ##cmakedefine FOO_STRING "@FOO_STRING@"
    ##define BAR_STRING "@BAR_STRING@"
    #と書いてある場合
    option(FOO_ENABLE "Enable Foo" ON)
    set(FOO_STRING "foo")
    set(BAR_STRING "bar")
    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/configure.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/configure.h" NEWLINE_STYLE LF @ONLY)
    ##define FOO_ENABLE
    ##define FOO_STRING "foo"
    ##define BAR_STRING "bar"
    #となる.
    
    #option(FOO_ENABLE "Enable Foo" ON)
    #set(FOO_STRING "foo")
    #set(BAR_STRING "bar")
    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/configure.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/configure.h" NEWLINE_STYLE LF @ONLY)
    #とすると,
    #/* #undef FOO_ENABLE */
    #/* #undef FOO_STRING */
    ##define BAR_STRING ""
    #となる.
    

  • コンパイラやBinutilsを設定

  • function(set_llvm_tools)
    
    if(WIN32)
    set(CMAKE_C_COMPILER "clang-cl" PARENT_SCOPE)
    set(CMAKE_CXX_COMPILER "clang-cl" PARENT_SCOPE)
    else()
    set(CMAKE_C_COMPILER "clang" PANRENT_SCOPE)
    set(CMAKE_CXX_COMPILER "clang++" PARENT_SCOPE)
    endif()
    
    set(CMAKE_AR "llvm-ar" PARENT_SCOPE)
    set(CMAKE_LINKER "llvm-ld" PARENT_SCOPE)
    set(CMAKE_NM "llvm-nm" PARENT_SCOPE)
    set(CMAKE_OBJDUMP "llvm-objdump" PANRET_SCOPE)
    set(CMAKE_RANLIB "llvm-ranlib" PARENT_SCOPE)
    endfunction(set_llvm_tools)
    
  • インクルードディレクトリ

  • # CMAKE_CURRENT_SOURCE_DIR変数は, 現在処理中のCMakeLists.txtのあるディレクトリ.
    # BEFORE or AFTER オプションは, パスリストへの追加位置.
    include_directories(AFTER ${CMAKE_CURRENT_SOURCE_DIR})
    

  • リンクディレクトリ

  • CMAKE_CURRENT_SOURCE_DIRからの相対パスになる.
    Visual Studioの場合以下のようにしないと上手く展開されない.
    link_directories("./lib")
    

  • ライブラリ検索

  • NAMES以降に, ライブラリ名のバリエーションを書く.
    先頭から順に検索して見つかったものが結果に入る.
    find_library(LIBRARY0 NAMES hoge0 PATHS "/libs/hoge")
    find_library(LIBRARY1 NAMES hoge1 PATHS "/libs/hoge")
    

  • 出力ディレクトリ

  • _<Configuration> を付けてコンフィギュレーション毎に設定.
    コンフィギュレーション毎の設定をしないと, 出力ディレクトリは, OUTPUT_DIRECTORY/CONFIGURATIONが設定される.
    # Executable file: CMAKE_RUNTIME_OUTPUT_DIRECTORY
    # Static library:  CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    # Shared library:  CMAKE_RUNTIME_OUTPUT_DIRECTORY
    
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug")
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/bin/Release")
    

  • 関数と返値

  • function(expand_files FILES SOURCE)
        file (GLOB SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCE})
        set(${FILES} ${SOURCES} PARENT_SCOPE)
    endfunction(expand_files)
    

  • 環境変数

  • セットする場合は$\$$を付けない. ゲットする場合は$\$$を付ける.
    # Set environment variable INCLUDE
    set(ENV{INCLUDE} "PATH0")
    set(ENV{INCLUDE} "$ENV{INCLUDE};PATH1")
    message("$ENV{INCLUDE}")
    
  • リスト

  • # Create list
    set(LIST_ a;b;c)
    message("${LIST_}")
    set(LIST_ "a" "b" "c")
    message("${LIST_}")
    set(LIST_ "a;b;c")
    message("${LIST_}")
    
    #
    list(LENGTH LIST_ LIST_LENGTH)
    message("${LIST_LENGTH}")
    list(GET LIST_ 0 LIST_VALUE)
    message("${LIST_VALUE}")
    
  • ファイルの収集, グルーピング

  • IDE用の設定と思われる.
    Visual Studioではファイルフィルタに相当.
    Visual Studioでは, ディレクトリ階層の区切りに'¥'を使用する.
    set(ROOT_INCLUDE "./include")
    set(ROOT_SOURCE "./src")
    set(MODULES "/")
    
    set(HEADERS "")
    set(SOURCES "")
    
    # Collect files
    foreach(MODULE IN LISTS MODULES)
        set(HFILES "")
        set(CPPFILES "")
        set(CFILES "")
        expand_files(HFILES "${ROOT_INCLUDE}${MODULE}/*h")
        expand_files(CPPFILES "${ROOT_SOURCE}${MODULE}/*cpp")
        expand_files(CFILES "${ROOT_SOURCE}${MODULE}/*c")
    
        # Append files to list
        set(HEADERS ${HEADERS} ${HFILES})
        set(SOURCES ${SOURCES} ${CPPFILES} ${CFILES})
    
        # Grouping files
        string(REPLACE "/" "\\" FILTER "include/${MODULE}")
        source_group("${FILTER}" FILES ${HEADERS})
        string(REPLACE "/" "\\" FILTER "src/${MODULE}")
        source_group("${FILTER}" FILES ${CPPFILES} ${CFILES})
    endforeach()
    

  • コンパイラ, リンカフラグ

  • if(MSVC)
        set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /D_MBCS /W4 /WX- /nologo /fp:precise /Zc:wchar_t /TP /Gd")
        set(CMAKE_CXX_FLAGS_DEBUG "/MTd /ZI /Ob0 /Od /RTC1 /Gy /GR- /GS /Gm-")
        set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /GL /GR-")
    
        #set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "")
        set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
    
    elseif(UNIX)
    elseif(APPLE)
    endif()
    

  • 出力設定

  • add_executable(${ProjectName} ${FILES})
    add_library(${ProjectName} STATIC ${FILES})
    add_library(${ProjectName} SHARED ${FILES})
    

  • ターゲット指定のコンパイラオプション

  • コンパイラオプションや出力ファイル名を, コンフィギュレーション毎に変えたいことがある.
    出力設定add_????の後に, 以下のように書く.
    プリプロセッサ定義をコンフィギュレーション毎に変える場合, set_propertyを使用して以下のようにする.
    set_target_properties(${ProjectName} PROPERTIES
        OUTPUT_NAME_DEBUG "${ProjectName}d"
        OUTPUT_NAME_RELEASE "${ProjectName}"
        COMPILE_DEFINITIONS "HOGE")
    
    #$<$<CONFIG:DEBUG>:DEBUG_MODE> means if CONFIG==DEBUG then expand DEBUG_MODE
    set_property(TARGET ${ProjectName} APPEND PROPERTY
            COMPILE_DEFINITIONS $<$<CONFIG:DEBUG>:DEBUG_MODE1> $<$<CONFIG:DEBUG>:DEBUG_MODE2>
            $<$<CONFIG:RELEASE>:RELEASE_MODE>)
    
    #Linker flags
    set_target_properties(${ProjectName} PROPERTIES
            LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE"
            LINK_FLAGS_RELEASE "/LTCG /SUBSYSTEM:CONSOLE")
    

  • コンフィギュレーション毎のリンクするライブラリ

  • リンクするライブラリを, コンフィギュレーション毎に変えたいことはよくある.
    インポート済みライブラリターゲットを作って, コンフィギュレーション毎にリンクしたいファイルを追加.
    そのライブラリを本体に追加する.
    add_library(GTEST MODULE IMPORTED)
    set_target_properties(GTEST PROPERTIES IMPORTED_LOCATION_DEBUG "gtestd.lib" IMPORTED_LOCATION_RELEASE "gtest.lib")
    target_link_libraries(${ProjectName} GTEST)
    


  • その他

  • その他雑多なもの.
  • Visual Studioのデバッグディレクトリを設定

  • # Set the wroking directory for Visual Studio
    function(set_vs_working_directory projectname path)
        file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${projectname}.vcxproj.user"
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>
    <Project ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
      <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
        <LocalDebuggerWorkingDirectory>${path}</LocalDebuggerWorkingDirectory>
        <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
      </PropertyGroup>
      <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
        <LocalDebuggerWorkingDirectory>${path}</LocalDebuggerWorkingDirectory>
        <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
      </PropertyGroup>
    </Project>")
    endfunction(set_vs_working_directory)
    



  • Visual Studioのインストールディレクトリをレジストリから取得


  • function(get_dir_from_list RESULT_VALUE INPUT_STR INDEX)
        string(REGEX REPLACE [\n\r] "" INPUT_STR ${INPUT_STR})
        string(REPLACE "    " ";" INPUT_LIST ${INPUT_STR})
        list(GET INPUT_LIST ${INDEX} INPUT_STR)
        string(REPLACE "\\" "/" INPUT_STR ${INPUT_STR})
        set(${RESULT_VALUE} ${INPUT_STR} PARENT_SCOPE)
    endfunction(get_dir_from_list)
    
    function(get_visualstudio_dir VS_DIR VERSIONS)
        set(VS_DIR "" PARENT_SCOPE)
        set(KEYS "HKLM;HKCU")
    # Search Wow64
        foreach(ver IN LISTS VERSIONS)
            foreach(key IN LISTS KEYS)
                execute_process(COMMAND reg query
                        "${key}\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\${ver}\\Setup\\VC" /v "ProductDir"
                        RESULT_VARIABLE REG_RESULT
                        OUTPUT_VARIABLE REG_VALUE)
                if(REG_RESULT EQUAL 0)
                    get_dir_from_list(REG_VALUE ${REG_VALUE} 3)
                    set(${VS_DIR} ${REG_VALUE} PARENT_SCOPE)
                    return()
                endif()
            endforeach(key)
        endforeach(ver)
    
    # Search 32bit
        foreach(ver IN LISTS VERSIONS)
            foreach(key IN LISTS KEYS)
                execute_process(COMMAND reg query
                        "${key}\\SOFTWARE\\Microsoft\\VisualStudio\\${ver}\\Setup\\VC" /v "ProductDir"
                        RESULT_VARIABLE REG_RESULT
                        OUTPUT_VARIABLE REG_VALUE)
                if(REG_RESULT EQUAL 0)
                    get_dir_from_list(REG_VALUE ${REG_VALUE} 3)
                    set(${VS_DIR} ${REG_VALUE} PARENT_SCOPE)
                    return()
                endif()
            endforeach(key)
        endforeach(ver)
    
    endfunction(get_visualstudio_dir)
    
    //Visual Studio 2015または2013のディレクトリを取得するなら
    get_visualstudio_dir(VS_DIR "14.0;12.0")
    

0 件のコメント:

コメントを投稿