連絡先 最初に戻る 戻る 次へ進む
$Date: 2017-05-14 17:13:45 +0900 (2017/05/14 (日)) $
$Revision: 1130 $

cmake での shared library/static library のテストプロジェクト

概要

shared library(DLL) と static library を使う場合をプロジェクト生成時(cmake 実行時) に動的に切り替えられる方法を説明します。

サンプルのプロジェクトの構成

│  CMakeLists.txt
│
├─Library
│      CMakeLists.txt
│      Library.c
│      Library.h
│
└─Program
        CMakeLists.txt
        Program.c
https://github.com/m-tmatma/cmake-sample.git の LibrarySample ディレクトリに格納されています。

library のプロジェクトの定義

Library/CMakeLists.txt
cmake_minimum_required(VERSION 2.6.4)

# define a variable of project name
set( project_name "Library")

# define a project name
project (${project_name})

# define a variable SRC with file GLOB
file(GLOB SRC *.c *.h)

# add include directory for ${project_name}_Export.h
include_directories(${PROJECT_BINARY_DIR})

# define sources files of an executable
add_library(${project_name} ${LIB_TYPE} ${SRC} ${PROJECT_BINARY_DIR}/${project_name}_Export.h)

include (GenerateExportHeader)
GENERATE_EXPORT_HEADER( ${project_name}
	BASE_NAME ${project_name}
	EXPORT_MACRO_NAME ${project_name}_EXPORT
	EXPORT_FILE_NAME ${project_name}_Export.h
	STATIC_DEFINE ${project_name}_BUILT_AS_STATIC
)
include_directories でインクルードディレクトリを指定します
${PROJECT_BINARY_DIR} はこのプロジェクトに対応するビルドディレクトリを意味します。
add_library でライブラリを定義します。${LIB_TYPE} のところで SHARED を指定すると shared Library(Windows ではDLL)になり,
STATIC を指定するとスタティックライブラリになります。
トップディレクトリにある CMakeLists.txt でこの変数を定義します。
以下の指定では Library_Export.h というDLL のインポート、エクスポート指定のためのヘッダファイルを作成するための命令です。
include (GenerateExportHeader)
GENERATE_EXPORT_HEADER( ${project_name}
	BASE_NAME ${project_name}
	EXPORT_MACRO_NAME ${project_name}_EXPORT
	EXPORT_FILE_NAME ${project_name}_Export.h
	STATIC_DEFINE ${project_name}_BUILT_AS_STATIC
)
以下のようなヘッダファイルが出力先に生成されます。
このファイルをインクルードするために include_directories(${PROJECT_BINARY_DIR}) の指定をしています。
#ifndef Library_EXPORT_H
#define Library_EXPORT_H

#ifdef Library_BUILT_AS_STATIC
#  define Library_EXPORT
#  define LIBRARY_NO_EXPORT
#else
#  ifndef Library_EXPORT
#    ifdef Library_EXPORTS
        /* We are building this library */
#      define Library_EXPORT __declspec(dllexport)
#    else
        /* We are using this library */
#      define Library_EXPORT __declspec(dllimport)
#    endif
#  endif

#  ifndef LIBRARY_NO_EXPORT
#    define LIBRARY_NO_EXPORT 
#  endif
#endif

#ifndef LIBRARY_DEPRECATED
#  define LIBRARY_DEPRECATED __declspec(deprecated)
#endif

#ifndef LIBRARY_DEPRECATED_EXPORT
#  define LIBRARY_DEPRECATED_EXPORT Library_EXPORT LIBRARY_DEPRECATED
#endif

#ifndef LIBRARY_DEPRECATED_NO_EXPORT
#  define LIBRARY_DEPRECATED_NO_EXPORT LIBRARY_NO_EXPORT LIBRARY_DEPRECATED
#endif

#if 0 /* DEFINE_NO_DEPRECATED */
#  ifndef LIBRARY_NO_DEPRECATED
#    define LIBRARY_NO_DEPRECATED
#  endif
#endif

#endif

exe のプロジェクトの定義

Program/CMakeLists.txt
cmake_minimum_required(VERSION 2.6.4)

# define a variable of project name
set( project_name sample_program)

# set the project as the startup project
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT ${project_name} )

# define a project name
project (${project_name})

# define a variable SRC with file GLOB
file(GLOB SRC *.c *.h)

# add include directory
include_directories(../Library)

# add include directory for ${project_name}_Export.h
include_directories(${PROJECT_BINARY_DIR}/../Library)

# define sources files of an executable
add_executable(${project_name} ${SRC})

# link a library
target_link_libraries(${project_name} Library)
include_directories でインクルードディレクトリの指定をしていますが、 ${PROJECT_BINARY_DIR} を参照する場合、Program のプロジェクトに対する生成ディレクトリなので Library のプロジェクトに対するフォルダを指定する必要があるので ../Library を追加しています。 target_link_libraries でリンクするライブラリを指定しています。

トップのプロジェクトの定義

CMakeLists.txt
cmake_minimum_required(VERSION 2.6.4)

# see https://cmake.org/Wiki/BuildingWinDLL
# Allow the developer to select if Dynamic or Static libraries are built
option (BUILD_SHARED_LIBS "Build Shared Libraries" ON)
# Set the LIB_TYPE variable to STATIC
set (LIB_TYPE STATIC)
if (BUILD_SHARED_LIBS)
  # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
  set (LIB_TYPE SHARED)
endif (BUILD_SHARED_LIBS)

project (LibraryTest)

set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT "sample_program" )

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_subdirectory(Library)
add_subdirectory(Program)

# turn on solution folder
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# create solution folder
set_target_properties(Library        PROPERTIES FOLDER library)
set_target_properties(sample_program PROPERTIES FOLDER executable)
以下定義で BUILD_SHARED_LIBS が ON になっていたら ${LIB_TYPE} は SHARED (Shared Library) になります。
option (BUILD_SHARED_LIBS "Build Shared Libraries" ON)
# Set the LIB_TYPE variable to STATIC
set (LIB_TYPE STATIC)
if (BUILD_SHARED_LIBS)
  # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
  set (LIB_TYPE SHARED)
endif (BUILD_SHARED_LIBS)
BUILD_SHARED_LIBS が OFF になっていたら ${LIB_TYPE} は STATIC (Static Library) になります。
そして BUILD_SHARED_LIBS はコマンドラインで cmake を実行するときに上書きすることができます。
以下のように実行してプロジェクトを生成すれば Shared Library (DLL) になります。
cmake -D BUILD_SHARED_LIBS=1 ..\cmake-sample\LibrarySample\
以下のように実行してプロジェクトを生成すれば Static Library になります。
cmake -D BUILD_SHARED_LIBS=0 ..\cmake-sample\LibrarySample\

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) でライブラリ出力先フォルダを指定します。
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) で実行ファイルの出力先フォルダを指定します。
CMAKE_BINARY_DIR の変数はビルドディレクトリのトップディレクトリを表します

CMake : out-of-sourceビルドで幸せになるを参考

add_subdirectory(Library) でライブラリ用のディレクトリをビルド対象に追加しています。

# turn on solution folder
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# create solution folder
set_target_properties(Library        PROPERTIES FOLDER library)
set_target_properties(sample_program PROPERTIES FOLDER executable)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) でソリューションフォルダの機能を有効にします。
set_target_properties(sample_program PROPERTIES FOLDER executable) で sample_program というプロジェクトを executable というソリューションフォルダに入れています。