2022年6月25日 星期六

CMake - Step 2: Adding A Library As An Option


很多時候我們會在專案中決定使用哪個library, 這裡會舉個範例, 使用自訂的library或是使用系統的library,首先要在最上層的CMakeLists.txt中用option()定義我們的變數USE_MYMATH, on代表用自訂的library, 否則用系統的library, 所以相對應的target_link_libraries()與target_include_directories()也要根據USE_MYMATH稍微做一下調整, 所以我們用EXTRA_LIBS與EXTRA_INCLUDES分別去儲存對應的header file位置與相關的library資訊
# Require a minimum version of cmake.
# cmake_minimum_required(VERSION <min>>[...<policy_max>] [FATAL_ERROR])
cmake_minimum_required(VERSION 3.10)

# Set the name of the project.
# project(<PROJECT-NAME< [<anguage-name>...])
# project(<PROJECT-NAME>
#         [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
#         [DESCRIPTION <project-description-string>]
#         [LANGUAGES <language-name>...])
project(Tutorial VERSION 0.1.2.3 DESCRIPTION "This is Brook 1st CMake Lib")

# Add an executable to the project using the specified source files.
# add_executable(<name> [WIN32] [MACOSX_BUNDLE]
#                [EXCLUDE_FROM_ALL]
#                [source1] [source2 ...])
add_executable(Tutorial hello.c)

# option(<variable> "<help_text>" [value])
option(USE_MYMATH "Use tutorial provided math implementation" ON)

# configure_file(<input> <output>
#               [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
#                FILE_PERMISSIONS <permissions>...]
#               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
#               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(Config.h.in Config.h)

if (USE_MYMATH)
# Add a subdirectory to the build.
# add_subdirectory(source_dir [binary_dir]
#                        [EXCLUDE_FROM_ALL])
add_subdirectory(mymath01)

# list(APPEND <list> [<element> ...])
# Appends elements to the list.
# If no variable named <list> exists in the current
# scope its value is treated as empty and the elements
# are appended to that empty list.
list(APPEND EXTRA_LIBS MyMathLib1)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/mymath01")
else()
list(APPEND EXTRA_LIBS "m")
endif()

# Specify libraries or flags to use when linking a given target and/or its dependents.
# target_link_libraries(<target>
#                      <PRIVATE|PUBLIC|INTERFACE> ...
#                      [<PRIVATE|PUBLIC|INTERFACE> ...]...)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})

# Add include directories to a target.
# target_include_directories(&;lt;target> [SYSTEM] [AFTER|BEFORE]
#   &;lt;INTERFACE|PUBLIC|PRIVATE> [items1...]
#   [&;lt;INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES})

接著會利用Config.h.in的cmakedefine去define USE_MYMATH, hello.c則需要include "Config.h"並且利用#ifdef/#else/#endif做一些對應的修改
[brook@:~/Projects/cmake/02-2]$ tree
.
`-- src
    |-- CMakeLists.txt
    |-- Config.h.in
    |-- hello.c
    `-- mymath01
        |-- CMakeLists.txt
        |-- mymath01.c
        `-- mymath01.h

2 directories, 6 files
[brook@:~/Projects/cmake/02-2]$ cat src/Config.h.in
#cmakedefine USE_MYMATH
[brook@:~/Projects/cmake/02-2]$ cat src/hello.c
#include <stdio.h>
#include <stdlib.h>
#include "Config.h"

#ifdef USE_MYMATH
#pragma message("use mymath")
#include "mymath01.h"
#else
#pragma message("use system")
#include 
#endif

int main(int argc, char *argv[])
{
#ifdef USE_MYMATH
        printf("mymath: %d\n", squar(atoi(argv[1])));
#else
        printf("system: %d\n", (int)pow(atoi(argv[1]), 2));
#endif
        return 0;
}

[brook@:~/Projects/cmake/02-2/build]$ cmake ../src
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- 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
-- Configuring done
-- Generating done
-- Build files have been written to: /build/brook/Projects/cmake/02-2/build
[brook@:~/Projects/cmake/02-2/build]$ make
Scanning dependencies of target MyMathLib1
[ 25%] Building C object mymath01/CMakeFiles/MyMathLib1.dir/mymath01.c.o
[ 50%] Linking C static library libMyMathLib1.a
[ 50%] Built target MyMathLib1
Scanning dependencies of target Tutorial
[ 75%] Building C object CMakeFiles/Tutorial.dir/hello.c.o
/build/brook/Projects/cmake/02-2/src/hello.c:6:9: note: #pragma message: use mymath
 #pragma message("use mymath")
         ^~~~~~~
[100%] Linking C executable Tutorial
[100%] Built target Tutorial
[brook@:~/Projects/cmake/02-2/build]$ ./Tutorial 3
mymath: 9
[brook@:~/Projects/cmake/02-2/build]$ cmake ../src/ -DUSE_MYMATH=off
-- Configuring done
-- Generating done
-- Build files have been written to: /build/brook/Projects/cmake/02-2/build
[brook@:~/Projects/cmake/02-2/build]$ make
Scanning dependencies of target Tutorial
[ 50%] Building C object CMakeFiles/Tutorial.dir/hello.c.o
/build/brook/Projects/cmake/02-2/src/hello.c:9:9: note: #pragma message: use system
 #pragma message("use system")
         ^~~~~~~
[100%] Linking C executable Tutorial
[100%] Built target Tutorial
[brook@:~/Projects/cmake/02-2/build]$ ./Tutorial 3
system: 9





沒有留言:

張貼留言

熱門文章