2022年6月11日 星期六
Table Of Content for "CMake Tutorial"
Step 1: A Basic Starting Point
Step 2: Adding a Library
- Step 2: Adding A Library As An Option
Step 3: Adding Usage Requirements for a Library
Step 4: Installing and Testing
Step 5: Adding System Introspection
Step 6: Adding a Custom Command and Generated File
Step 7: Packaging an Installer
Step 8: Adding Support for a Testing Dashboard
Step 9: Selecting Static or Shared Libraries
Step 10: Adding Generator Expressions
Step 11: Adding Export Configuration
Step 12: Packaging Debug and Release
標籤:
- Table Of Content,
cmake
2022年6月3日 星期五
CMake - Step 1: A Basic Starting Point
本文是CMake Tutorial的心得, CMake是一個用於build, test與package的cross-platform tool, 基本上是透過撰寫CMakeLists來描述如何build, test與package專案,接著會產生makefile, 再透過makefile產生最終的target(executable, library, or both)
讓我們從最簡單的CMakeLists.txt開始,基本上CMakeLists.txt的指令是不分大小寫的
# 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>] # [HOMEPAGE_URL <url-string>] # [LANGUAGES <language-name>...]) project(Tutorial VERSION 0.1.2 DESCRIPTION "This is Brook 1st CMake") # 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)
hello.c
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { printf("hello world\n"); return 0; }
有了CMakeLists.txt與source code, 就可以使用cmake [options] <path-to-source>建立Makefile, 並使用cmake --build <dir>去build targe
[brook@:~/Projects/cmake]$ tree . `-- src |-- CMakeLists.txt `-- hello.c 1 directory, 2 files [brook@:~/Projects/cmake]$ mkdir build && cd build [brook@:~/Projects/cmake/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/build [brook@:~/Projects/cmake/build]$ ls CMakeCache.txt CMakeFiles Makefile cmake_install.cmake [brook@:~/Projects/cmake/build]$ cmake --build . Scanning dependencies of target Tutorial [ 50%] Building C object CMakeFiles/Tutorial.dir/hello.c.o [100%] Linking C executable Tutorial [100%] Built target Tutorial [brook@:~/Projects/cmake/build]$ ls CMakeCache.txt CMakeFiles Makefile Tutorial cmake_install.cmake [brook@:~/Projects/cmake/build]$ ./Tutorial hello world
Adding a Version Number and Configured Header File
前面的CMakeLists.txt中描述了project(Tutorial VERSION 0.1.2 DESCRIPTION "This is Brook 1st CMake"), 但是沒在C code中被用到, 所以, 我們將這些變數加入configure a header file 並傳遞給source code# 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 DESCRIPTION "This is Brook 1st CMake") # 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) # Copy a file to another location and modify its contents. # 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_file(Config.h.in Config.h) # 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}")
首先先透過configure_file()設定configure file的input與output, 在CMake建立Makefile過程中, 就會將configure的input變數取代後, 產生configure的output檔. 由於configure header file要被source code給include進來, 所以還得透過target_include_directories()設定對應的include path. 相關執行步驟如下:
[brook@:~/Projects/cmake]$ tree . `-- src |-- CMakeLists.txt |-- Config.h.in `-- hello.c 1 directory, 3 files [brook@:~/Projects/cmake]$ cat src/Config.h.in // the configured options and settings for Tutorial #define VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define VERSION_MINOR @Tutorial_VERSION_MINOR@ [brook@:~/Projects/cmake]$ cat src/hello.c #include <stdio.h> #include <stdlib.h> #include "Config.h" int main(int argc, char *argv[]) { printf("hello world(version: %d.%d)\n", VERSION_MAJOR, VERSION_MINOR); return 0; } [brook@:~/Projects/cmake]$ mkdir build && cd build [brook@:~/Projects/cmake/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/build [brook@:~/Projects/cmake/build]$ ls CMakeCache.txt CMakeFiles Config.h Makefile cmake_install.cmake [brook@:~/Projects/cmake/build]$ cmake --build . Scanning dependencies of target Tutorial [ 50%] Building C object CMakeFiles/Tutorial.dir/hello.c.o [100%] Linking C executable Tutorial [100%] Built target Tutorial [brook@:~/Projects/cmake/build]$ ./Tutorial hello world(version: 0.1) [brook@:~/Projects/cmake/build]$ cat Config.h // the configured options and settings for Tutorial #define VERSION_MAJOR 0 #define VERSION_MINOR 1
在這裡我們有用到幾個CMake的變數, 包含PROJECT_BINARY_DIR, <PROJECT-NAME>_VERSION_MAJOR, PROJECT_BINARY_DIR等等, 這些都可以參考cmake-variables(7)取得更多的變數與相關細節, 我這裡就簡單介紹幾個基本的, 並透過Configure header file讓大家稍微理解一下對應的值
[brook@:~/Projects/cmake/build]$ cat ../src/Config.h.in // the configured options and settings for Tutorial #define VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define VERSION_MINOR @Tutorial_VERSION_MINOR@ // <PROJECT-NAME>_BINARY_DIR // A variable is created with the name used in the project() command, // and is the binary directory for the project. #define Tutorial_BINARY_DIR @Tutorial_BINARY_DIR@ // <PROJECT-NAME>_SOURCE_DIR // Top level source directory for the named project. // A variable is created with the name used in the project() command, // and is the source directory for the project. #define Tutorial_SOURCE_DIR @Tutorial_SOURCE_DIR@ // <PROJECT-NAME>_VERSION // Value given to the VERSION option of the most recent call // to the project() command with project name <PROJECT-NAME> #define Tutorial_VERSION "@Tutorial_VERSION@" #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #define Tutorial_VERSION_PATCH @Tutorial_VERSION_PATCH@ #define Tutorial_VERSION_TWEAK @Tutorial_VERSION_TWEAK@ // Full path to build directory for project. // This is the binary directory of the most recent project() command. #define PROJECT_BINARY_DIR @PROJECT_BINARY_DIR@ // Short project description given to the project command. // This is the description given to the most recent project() command. #define PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@" // Name of the project given to the project command. // This is the name given to the most recent project() command. #define PROJECT_NAME @PROJECT_NAME@ // Top level source directory for the current project. // This is the source directory of the most recent project() command. #define PROJECT_SOURCE_DIR @PROJECT_SOURCE_DIR@ // Value given to the VERSION option of the most recent call to the project() command #define PROJECT_VERSION "@PROJECT_VERSION@" #define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define PROJECT_VERSION_TWEAK @PROJECT_VERSION_TWEAK@ [brook@:~/Projects/cmake/build]$ cmake ../src/ -- Configuring done -- Generating done -- Build files have been written to: /build/brook/Projects/cmake/build [brook@:~/Projects/cmake/build]$ cat Config.h // the configured options and settings for Tutorial #define VERSION_MAJOR 0 #define VERSION_MINOR 1 // <PROJECT-NAME>_BINARY_DIR // A variable is created with the name used in the project() command, // and is the binary directory for the project. #define Tutorial_BINARY_DIR /build/brook/Projects/cmake/build // <PROJECT-NAME>_SOURCE_DIR // Top level source directory for the named project. // A variable is created with the name used in the project() command, // and is the source directory for the project. #define Tutorial_SOURCE_DIR /build/brook/Projects/cmake/src // <PROJECT-NAME>_VERSION // Value given to the VERSION option of the most recent call // to the project() command with project name <PROJECT-NAME> #define Tutorial_VERSION "0.1.2" #define Tutorial_VERSION_MAJOR 0 #define Tutorial_VERSION_MINOR 1 #define Tutorial_VERSION_PATCH 2 #define Tutorial_VERSION_TWEAK // Full path to build directory for project. // This is the binary directory of the most recent project() command. #define PROJECT_BINARY_DIR /build/brook/Projects/cmake/build // Short project description given to the project command. // This is the description given to the most recent project() command. #define PROJECT_DESCRIPTION "This is Brook 1st CMake" // Name of the project given to the project command. // This is the name given to the most recent project() command. #define PROJECT_NAME Tutorial // Top level source directory for the current project. // This is the source directory of the most recent project() command. #define PROJECT_SOURCE_DIR /build/brook/Projects/cmake/src // Value given to the VERSION option of the most recent call to the project() command #define PROJECT_VERSION "0.1.2" #define PROJECT_VERSION_MAJOR 0 #define PROJECT_VERSION_MINOR 1 #define PROJECT_VERSION_PATCH 2 #define PROJECT_VERSION_TWEAK
2022年5月7日 星期六
Linux Kernel(2.1)- MAJRO NUMBER RESERVED FOR DYNAMIC ASSIGNMENT
Documentation/admin-guide/devices.txt 文檔中描述了各個major number的用途, 而這文章的重點是dynamic的範圍從234~254與384~511
234-254 char RESERVED FOR DYNAMIC ASSIGNMENT Character devices that request a dynamic allocation of major number will take numbers starting from 254 and downward. 384-511 char RESERVED FOR DYNAMIC ASSIGNMENT Character devices that request a dynamic allocation of major number will take numbers starting from 511 and downward, once the 234-254 range is full.
相關的代碼如下:
__register_chrdev_region() |-> find_dynamic_major() |-> 254 ~ 234 or 511 ~ 384 有空的就拿來用 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) { struct char_device_struct *cd; cd = __register_chrdev_region(0, baseminor, count, name); if (IS_ERR(cd)) return PTR_ERR(cd); *dev = MKDEV(cd->major, cd->baseminor); return 0; } static struct char_device_struct * __register_chrdev_region(unsigned int major, unsigned int baseminor, int minorct, const char *name) { struct char_device_struct *cd, *curr, *prev = NULL; int ret; int i; if (major >= CHRDEV_MAJOR_MAX) { pr_err("CHRDEV \"%s\" major requested (%u) is greater than the maximum (%u)\n", name, major, CHRDEV_MAJOR_MAX-1); return ERR_PTR(-EINVAL); } if (minorct > MINORMASK + 1 - baseminor) { pr_err("CHRDEV \"%s\" minor range requested (%u-%u) is out of range of maximum range (%u-%u) for a single major\n", name, baseminor, baseminor + minorct - 1, 0, MINORMASK); return ERR_PTR(-EINVAL); } cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); if (cd == NULL) return ERR_PTR(-ENOMEM); mutex_lock(&chrdevs_lock); if (major == 0) { ret = find_dynamic_major(); if (ret < 0) { pr_err("CHRDEV \"%s\" dynamic allocation region is full\n", name); goto out; } major = ret; } ret = -EBUSY; i = major_to_index(major); for (curr = chrdevs[i]; curr; prev = curr, curr = curr->next) { if (curr->major < major) continue; if (curr->major > major) break; if (curr->baseminor + curr->minorct <= baseminor) continue; if (curr->baseminor >= baseminor + minorct) break; goto out; } cd->major = major; cd->baseminor = baseminor; cd->minorct = minorct; strlcpy(cd->name, name, sizeof(cd->name)); if (!prev) { cd->next = curr; chrdevs[i] = cd; } else { cd->next = prev->next; prev->next = cd; } mutex_unlock(&chrdevs_lock); return cd; out: mutex_unlock(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); } /* fs/char_dev.c */ #define CHRDEV_MAJOR_MAX 512 /* Marks the bottom of the first segment of free char majors */ #define CHRDEV_MAJOR_DYN_END 234 /* Marks the top and bottom of the second segment of free char majors */ #define CHRDEV_MAJOR_DYN_EXT_START 511 #define CHRDEV_MAJOR_DYN_EXT_END 384 #define CHRDEV_MAJOR_HASH_SIZE 255 static struct char_device_struct { struct char_device_struct *next; unsigned int major; unsigned int baseminor; int minorct; char name[64]; struct cdev *cdev; /* will die */ } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; static int find_dynamic_major(void) { int i; struct char_device_struct *cd; /* from 254 ~ 234 */ for (i = ARRAY_SIZE(chrdevs)-1; i >= CHRDEV_MAJOR_DYN_END; i--) { if (chrdevs[i] == NULL) return i; } /* from 511 ~ 384 */ for (i = CHRDEV_MAJOR_DYN_EXT_START; i >= CHRDEV_MAJOR_DYN_EXT_END; i--) { for (cd = chrdevs[major_to_index(i)]; cd; cd = cd->next) if (cd->major == i) break; if (cd == NULL) return i; } return -EBUSY; }
標籤:
Linux - kernel
訂閱:
文章 (Atom)
熱門文章
-
轉自 http://www.wretch.cc/blog/redsonoma/14021073 基本概念: 1> tty(終端設備的統稱): tty一詞源於Teletypes,或者teletypewriters,原來指的是電傳打字機,是通過串行線用打印機鍵盤通過閱...
-
Work queue提供一個interface,讓使用者輕易的建立kernel thread並且將work綁在這個kernel thread上面,如下圖[1]所示。 由於work queue是建立一個kernel thread來執行,所以是在process context...
-
(V)將介紹file operations中的ioctl。ioctl的prototype為: int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); ...
-
這兩天電腦的word忽然都不能存檔,即便是另存新檔也不行,最後都只能放棄修改檔案,即便重新安裝過或者更新成2007也都不能存檔,最後就乖乖的google一下,原來是暫存的資料夾不存在,按照以下方式就可以解決了。 資料來源: word 2003不能存檔問題 編輯機碼的(reg...
-
System Call在HW和user space提供一層抽象層,主要目的有: 為user space提供硬體抽象層。比如,讀取檔案時,不用管檔案所在的媒體類型與檔案儲存類型。 System call能確保系統的安全與穩定。避免user space的無意或惡意的破壞。 ...
-
在kernel中建立thread可以使用kthread_create(),建立一個task,然後在調用wake_up_process(task)讓task真正的運行,如果要kill一個kthread可以使用kthread_stop()。 在kernel中,將kthread_cr...
-
Linux module練習手札I紀錄如何撰寫一個簡單的module,並且編輯它,以及load和unload一個module。 write a module #include <linux/init.h> #include <linux/module.h...
-
幾乎任何使用 TCP,UDP或UNIX-domain socket的動作都可以用nc來達成,常見的功能如。 simple TCP proxies shell-script based HTTP clients and servers network daemon testi...
-
很多人心中都有過一個問題 What is the difference between Platform driver and normal device driver? ,簡單的來說Platform devices就non-discoverable,也就是device本身沒辦法...
-
組成元件 要能正確顯示資料,必須包含資料倉儲(Store),資料欄位的定義(ColumnModel)。 首先我們先定義資料欄位: var cm = new Ext.grid.ColumnModel({ {header: 'Name', dataIndex...