Kicad根目录CmakeList解析
提示:想学习cmake的看此篇文章也用处多多
代码段序号 | 代码段简介 | 具体介绍 |
---|---|---|
1 | 定义环境要求和编译方式 | |
2 | 定义所需的option | |
3 | 设置一些编译的全局变量 | :符号隐藏、使用相对路径、c++版本 |
4 | 设置调试工具 | |
5 | 添加需要链接的库文件目录 | |
6 | 设置config文件路径和默认安装路径 | |
7 | 生成生成系统特定的头文件 | (以cmake的方式生成不同头文件,而不是ifdef来生成不同的头文件) |
8 | 设置编译器警告 | |
9 | 配置windows下运行的变量 | 编码方式、操作系统位数、其他依赖于arch的步骤 |
10 | 提供访问CCACHE的权限 | |
11 | 提供访问DISTCC的权限 | |
12 | 通过为GCC设置标志,或将llvm视为GCC | |
13 | 定义安装项的位置 | |
14 | 查找生成KiCad所需的库 | |
15 | 生成配置文件config.h | |
16 | 生成Map文件 | |
17 | 设置卸载规则 | |
18 | 设置安装 | |
19 | 构建子目录 |
cmake_minimum_required( VERSION 3.10 FATAL_ERROR )
if( DEFINED CMAKE_BUILD_TYPE )
set( CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Set to either \"Release\" or \"Debug\"" )
else()
set( CMAKE_BUILD_TYPE Release CACHE STRING "Set to either \"Release\" or \"Debug\"" )
endif()
如果编译类型未提前设置,则默认改为Release
涉及知识点 | 知识点介绍 |
---|---|
CMAKE_BUILD_TYPE 作用 | 指定单一生成器上的编译类型 |
CMAKE_BUILD_TYPE 可能的值 | Debug, Release, RelWithDebInfo, MinSizeRel |
set 函数用法 | 1. 赋值给一般变量。ex: set(FOO “x”)。 //FOO作用域为当前作用域。 set(FOO “x” PARENT_SCOPE) //FOO作用域跳上一级。 2. Set赋值给缓存变量。set( 缓存变量可以理解为当第一次运行cmake时,这些变量缓存到一份文件中(即编译目录下的CMakeCache.txt)。当再次运行cmake时,这些变量会直接使用缓存值。docstring是变量的简介。ex: set(FOO, “x” CACHE ) //原缓存中没有FOO则将FOO赋值为x且存入cache中。 //原缓存中有FOO则不做任何改变,即便原cache中FOO存的不是x。 3. 设置环境变量:set(ENV{} [])。 设置环境变量的值为 |
project( kicad )
设置项目名称
涉及知识点 | 知识点介绍 |
---|---|
project函数用法 | project( [VERSION [DESCRIPTION [HOMEPAGE_URL [LANGUAGES PROJECT-NAME:项目名称配置好值后,会存在CMAKE_PROJECT_NAME 变量中。 DESCRIPTION、HOMEPAGE_URL选项暂不支持。 VERSION:版本号,主要分为 major(主版本号)、minor(次版本号)、patch(补丁版本号)、tweak, 格式为: 10.2.1.3。设置对应的值后,会依次解析,存在各自对应的变量里面。 LANGUAGES: 可选,如果未配置,默认使用 C 以及 CXX。 ex: project(DEMO VERSION 10.2.1.3 LANGUAGES CXX C ASM ) 抽取变量: CMAKE_PROJECT_NAME = DEMO PROJECT_VERSION =10.2.1.3 PROJECT_VERSION_MAJOR = 10 PROJECT_VERSION_MINOR = 2 PROJECT_VERSION_PATCH = 1 PROJECT_VERSION_TWEAK = 3 |
include( GNUInstallDirs )
include( CMakeDependentOption )
# Path to local CMake modules.
set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules )
添加cmake下的两个module。并设置Cmake modules的路径(即本项目所写.cmake文件位置)
设置项目名称
涉及知识点 | 知识点介绍 |
---|---|
include函数 | 将本项目module下(CMAKE_MODULE_PATH定义的目录)或者cmake安装目录下的.cmake文件加载到此处。与C++中的include用法一致 |
GNUInstallDirs作用 | 定义GNU标准的安装路径,提供《GNU编程标准》定义的安装路径变量: CMAKE_INSTALL_ CMAKE_INSTALL_FULL_ CMAKE_INSTALL_ 其中 BINDIR—>bin SBINDIR—>sbin INCLUDEDIR—>include等等,具体请查看Cmake\share\cmake-3.xx\Modules下相应的.cmake文件 |
CMakeDependentOption作用 | 提供一个宏:提供一个option依赖于其他option。ex: cmake_dependent_option(USE_FOO “Use Foo” ON “USE_BAR;NOT USE_ZOT” OFF) 如果USE_BAR为true,USE_ZOT为false,则USE_FOO置为ON。否则为OFF |
option( KICAD_SCRIPTING
"Build the Python scripting support inside KiCad binaries (default ON)."
ON )
option( KICAD_SCRIPTING_MODULES
"Build native portion of the pcbnew Python module: _pcbnew.{pyd,so} for OS command line use of Python."
ON )
option( KICAD_SCRIPTING_PYTHON3
"Build for Python 3 instead of 2 (default OFF)."
OFF )
option( KICAD_SCRIPTING_WXPYTHON
"Build wxPython implementation for wx interface building in Python and py.shell (default ON)."
ON )
option( KICAD_SCRIPTING_WXPYTHON_PHOENIX
"Use new wxPython binding (default OFF)."
OFF )
option( KICAD_SCRIPTING_ACTION_MENU
"Build a tools menu with registered python plugins: actions plugins (default ON)."
ON )
option( KICAD_USE_OCE
"Build tools and plugins related to OpenCascade Community Edition (default ON)"
ON )
option( KICAD_USE_OCC
"Build tools and plugins related to OpenCascade Technology (overrides KICAD_USE_OCE, default OFF)"
OFF )
option( KICAD_INSTALL_DEMOS
"Install KiCad demos and examples (default ON)"
ON )
option( KICAD_BUILD_QA_TESTS
"Build software Quality assurance unit tests (default ON)"
ON )
option( KICAD_SPICE
"Build KiCad with internal Spice simulator."
ON )
option( KICAD_BUILD_I18N
"Build the translation libraries."
OFF )
option( KICAD_I18N_UNIX_STRICT_PATH
"Use standard Unix locale lookup path (default OFF)."
OFF )
# Not supported by all platforms (for instance mingw)
option( KICAD_SANITIZE_ADDRESS
"Build KiCad with sanitizer options. WARNING: Not compatible with gold linker"
OFF )
# Not supported by all platforms (for instance mingw)
option( KICAD_SANITIZE_THREADS
"Build KiCad with sanitizer options. WARNING: Not compatible with gold linker"
OFF )
option( KICAD_STDLIB_DEBUG
"Build KiCad with libstdc++ debug flags enabled."
OFF )
option( KICAD_STDLIB_LIGHT_DEBUG
"Build KiCad with libstdc++ with -Wp,-D_GLIBCXX_ASSERTIONS flag enabled. Not as intrusive as KICAD_STDLIB_DEBUG"
OFF )
cmake_dependent_option( KICAD_WIN32_BUILD_PARALLEL_CL_MP
"Build in parallel using the /MP compiler option (default OFF for safety reasons)"
OFF "WIN32" OFF )
option( KICAD_USE_VALGRIND
"Build KiCad with valgrind stack tracking enabled."
OFF )
option( KICAD_NETLIST_QA
"Run eeschema netlist QA tests (requires Python 3)"
OFF )
cmake_dependent_option( KICAD_WIN32_DPI_AWARE
"Turn on DPI awareness for Windows builds only"
OFF "WIN32" OFF )
cmake_dependent_option( KICAD_WIN32_CONTEXT_WINFIBER
"Use win32 fibers for libcontext"
OFF "WIN32" OFF )
option( KICAD_USE_EGL
"Build KiCad with EGL backend support for Wayland."
OFF )
cmake_dependent_option( KICAD_USE_BUNDLED_GLEW
"Use the bundled version of GLEW - only available when KICAD_USE_EGL is set"
ON "KICAD_USE_EGL"
OFF )
option( KICAD_DRC_PROTO
"Build the DRC prototype QA tool"
OFF )
option( KICAD_GAL_PROFILE
"Enable profiling info for GAL"
OFF )
#KICAD_SCRIPTING控制着整个python脚本系统。如果它为OFF,其他有关脚本的方法都不能运行。
if ( NOT KICAD_SCRIPTING )
message( STATUS "KICAD_SCRIPTING is OFF: Disabling all python scripting support" )
set( KICAD_SCRIPTING_MODULES OFF )
set( KICAD_SCRIPTING_ACTION_MENU OFF )
set( KICAD_SCRIPTING_PYTHON3 OFF )
set( KICAD_SCRIPTING_WXPYTHON OFF )
set( KICAD_SCRIPTING_WXPYTHON_PHOENIX OFF)
endif()
# KICAD_SCRIPTING_WXPYTHON_PHOENIX 需要打开KICAD_SCRIPTING_WXPYTHON 使wxWidgets库版本正确
if ( KICAD_SCRIPTING AND NOT KICAD_SCRIPTING_WXPYTHON AND KICAD_SCRIPTING_WXPYTHON_PHOENIX )
message( STATUS
"KICAD_SCRIPTING_WXPYTHON_PHOENIX has been requested, setting KICAD_SCRIPTING_WXPYTHON to ON")
set( KICAD_SCRIPTING_WXPYTHON ON)
endif()
# Global setting: 符号隐藏
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
通常库不太可能是单文件组成,这些文件中有些是做接口给外部使用,有些则单纯的只是库的内部实现。对于外部使用者来说,内部实现的这些符号没有实际的作用,理论上我们完全可以像对待文件内部符号一样把它们统统隐藏掉。不同的编译器提供了不同的方式来完成这件事情。
作用如下:
1. 安全,去掉不必要的符号,可以增加逆向破解的难度。
2. 压缩空间,符号实际上是放在 dll 中的,去掉这些符号可以缩减 dll 的大小
3. 性能,符号隐藏掉意味着它不会参与到动态链接过程,编译器可以有更大的优化空间,可能会产生更好的性能。
MSVC和GCC在动态库符号的默认属性上面有较大的差别,MSVC默认所有的符号都是隐藏的,而GCC默认所有的符号都是可见的。
使用MSVC编译可以什么都不做。使用GCC编译器加上-fvisibility=hidden选项,或加上-fvisibility-inlines-hidden把内联函数隐藏掉。如果使用Autotool,设置LD_CXXFLAG来控制默认隐藏,如果使用CMake,可以通过set(CMAKE_CXX_VISIBILITY_PRESET hidden)来完成。
# Global setting: 生成均使用绝对路径
set( CMAKE_POSITION_INDEPENDENT_CODE ON )
确定是否创建位置无关的可行性文件或共享库。对于SHARED和MODULE库目标,此属性默认为True,否则为False。
# Global setting: 设置C++版本,用来配置编译器
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
编译的版本为C++ 14,它不是可选的,不且使用任何GNU或MS扩展
涉及知识点 | 知识点介绍 |
---|---|
CXX_STANDARD作用 | 98, 11, 14, 17, 20, 23 |
CMAKE_CXX_STANDARD_REQUIRED作用 | 如果此属性设置为“ON”,则CXX STANDARD目标属性的值将被视为一个要求。如果此属性为OFF或unset,则CXX STANDARD target属性将被视为可选属性,如果请求的属性不可用,则该属性可能会“衰减”为以前的标准。 |
CMAKE_CXX_EXTENSIONS 作用 | 此属性指定是否应使用编译器特定的扩展。对于某些编译器,这会导致在编译行中添加一个标记,例如-std=gnu++11,而不是-std=c++11。 |
# 启动内存泄漏检测工具valgrind
if( KICAD_USE_VALGRIND )
add_definitions( -DKICAD_USE_VALGRIND )
endif()
#目前还未知GAL是用来做什么
if( KICAD_GAL_PROFILE )
add_definitions( -DKICAD_GAL_PROFILE )
endif()
# 确保debug模式在各种编译器上都可以被定义
set_property( DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUG> )
LINK_DIRECTORIES( ${LINK_DIRECTORIES_PATH} )
添加需要链接的库文件目录。它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。
set( KICAD_CONFIG_DIR "kicad" CACHE STRING "Location of user specific KiCad config files" )
mark_as_advanced( KICAD_CONFIG_DIR )
add_definitions( -DKICAD_CONFIG_DIR=${KICAD_CONFIG_DIR} )
if( NOT DEFAULT_INSTALL_PATH )
set( DEFAULT_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}"
CACHE
PATH
"Location of KiCad data files." )
endif()
设置KICAD_CONFIG_DIR(C:\Users\yin\AppData\Roaming存储用户操作等),添加预编译宏。
设置DEFAULT_INSTALL_PATH,自动生成到config.h文件中。
涉及知识点 | 知识点介绍 |
---|---|
mark_as_advanced函数作用 | mark_as_advanced([CLEAR|FORCE] VAR VAR2 VAR…) 标记已命名的缓冲变量为 advanced。 将缓存的变量标记为高级变量。其中,高级变量指的是那些在cmake GUI中,只有当”显示高级选项“被打开时才会被显示的变量。如果CLEAR是第一个选项,参数中的高级变量将变回非高级变量。如果FORCE是第一个选项,参数中的变量会被提升为高级变量。如果两者都未出现,新的变量会被标记为高级变量;如果这个变量已经是高级/非高级状态的话,它会维持原状。 |
include( PerformFeatureChecks )
perform_feature_checks()
此处调用了CMakeModules下面的PerformFeatureChecks.cmake文件.
使用cmake来探查系统特定的依赖同时更新配置头文件。
include( ${CMAKE_MODULE_PATH}/Warnings.cmake )
if( KICAD_WIN32_CONTEXT_WINFIBER )
set(LIBCONTEXT_USE_WINFIBER true)
add_compile_definitions(LIBCONTEXT_USE_WINFIBER)
else()
set(LIBCONTEXT_USE_WINFIBER false)
endif()
此处调用了CMakeModules下面的Warning.cmake文件.
设置是否使用winfiber(纤程)
涉及知识点 | 知识点介绍 |
---|---|
add_compile_definitions函数作用 | 将预处理器定义添加到编译器命令行。 |
add_definitions(-DUNICODE -D_UNICODE)
KiCad使用的是unicode的编码方式。
add_definitions( -D_USE_MATH_DEFINES )
在标准编译模式下,M_PI德国变量只有在_USE_MATH_DEFINES被设置的时候才会定义。
if( MSVC )
#此段代码暂时用不到
else()
if ( NOT CMAKE_SIZEOF_VOID_P EQUAL 8 )
set( KICAD_BUILD_ARCH "x86" )
set( KICAD_BUILD_ARCH_X86 1 )
elseif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
set( KICAD_BUILD_ARCH "x64" )
set( KICAD_BUILD_ARCH_X64 1 )
endif()
endif()
add_definitions( -DKICAD_BUILD_ARCH=${KICAD_BUILD_ARCH} )
if( KICAD_WIN32_DPI_AWARE )
add_definitions( -DKICAD_WIN32_DPI_AWARE=1 )
endif()
设置用于资源编译器和其他依赖于arch的变量和宏。MSVC编译器目前还未编译成功,所以先不关注MSVC。
涉及知识点 | 知识点介绍 |
---|---|
CMAKE_SIZEOF_VOID_P作用 | 空指针的大小。32位机:4个字节;64位机:8个字节 |
add_definitions( -D_USE_MATH_DEFINES )
设置DPI感知。
涉及知识点 | 知识点介绍 |
---|---|
DPI感知 | 当应用程序具有系统DPI感知功能时,它将从主监视器获取缩放设置,无论缩放设置如何,都可以正确缩放和渲染应用程序。 在显示器上,每英寸点数(DPI)定义构成面板的每个物理单元的像素数。 传统上,显示器每英寸输出96像素,但随着技术的发展,公司开始增加同一物理空间中的像素数,导致屏幕上的DPI达到200甚至更高。 虽然较高的像素密度有助于确保更清晰的图像,但是需要一种显示缩放形式来正确地调整屏幕上的元素。 否则,视觉元素和文本将显得非常小,以至于难以使用。 |
if (USE_CCACHE)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
set(RULE_LAUNCH_COMPILE "${RULE_LAUNCH_COMPILE} ${CCACHE_FOUND}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${RULE_LAUNCH_COMPILE})
get_property(RULE_LAUNCH_LINK GLOBAL PROPERTY RULE_LAUNCH_LINK)
set(RULE_LAUNCH_LINK "${RULE_LAUNCH_LINK} ${CCACHE_FOUND}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${RULE_LAUNCH_LINK})
message(STATUS "Used ${CCACHE_FOUND} for compilation.")
else(CCACHE_FOUND)
message(STATUS "CCache was requested but not found.")
endif(CCACHE_FOUND)
endif(USE_CCACHE)
涉及知识点 | 知识点介绍 |
---|---|
CCACHE工具(暂时不用) | cache(“compiler cache”的缩写)工具会高速缓存编译生成的信息,并在编译的特定部分使用高速缓存的信息, 比如头文件,这样就节省了通常使用 cpp 解析这些信息所需要的时间。 安装ccache之后,需要告诉CMake将其用作编译器的外壳。如下操作 find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) endif(CCACHE_FOUND) |
find_program函数 | find_program( name1 [path1 path2 …]) 在特定路径下查找文件 |
if (USE_DISTCC)
find_program(DISTCC_FOUND distcc)
if(DISTCC_FOUND)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
set(RULE_LAUNCH_COMPILE "${RULE_LAUNCH_COMPILE} ${DISTCC_FOUND}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${RULE_LAUNCH_COMPILE})
message(STATUS "Using ${DISTCC_FOUND} for distributed build.")
else(DISTCC_FOUND)
message(INFO "Distcc was requested but not found.")
endif(DISTCC_FOUND)
endif(USE_DISTCC)
涉及知识点 | 知识点介绍 |
---|---|
DISTCC工具(暂时不用) | 分布式编译的工具。 |
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
涉及知识点 | 知识点介绍 |
---|---|
CMAKE_COMPILER_IS_GNUCXX | 如果C++(CXX)编译器是GNU则为True |
CMAKE_CXX_COMPILER_ID | 编译器供应商独有的短字符串。包括: Absoft = Absoft Fortran (absoft.com) ADSP = Analog VisualDSP++ (analog.com) AppleClang = Apple Clang (apple.com) ARMCC = ARM Compiler (arm.com) ARMClang = ARM Compiler based on Clang (arm.com) Bruce = Bruce C Compiler CCur = Concurrent Fortran (ccur.com) Clang = LLVM Clang (clang.llvm.org) Cray = Cray Compiler (cray.com Embarcadero, Borland = Embarcadero (embarcadero.com) Flang = Flang LLVM Fortran Compiler G95 = G95 Fortran (g95.org) GNU = GNU Compiler Collection (gcc.gnu.org) GHS = Green Hills Software (www.ghs.com) HP = Hewlett-Packard Compiler (hp.com) IAR = IAR Systems (iar.com) Intel = Intel Compiler (intel.com) MSVC = Microsoft Visual Studio (microsoft.com) NVIDIA = NVIDIA CUDA Compiler (nvidia.com) OpenWatcom = Open Watcom (openwatcom.org) PGI = The Portland Group (pgroup.com) PathScale = PathScale (pathscale.com) SDCC = Small Device C Compiler (sdcc.sourceforge.net) SunPro = Oracle Solaris Studio (oracle.com) TI = Texas Instruments (ti.com) TinyCC = Tiny C Compiler (tinycc.org) XL, VisualAge, zOS = IBM XL (ibm.com) XLClang = IBM Clang-based XL (ibm.com) |
# 32位系统下为GCC设置32位标志以防止精度过高
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
set( CMAKE_CXX_FLAGS "-ffloat-store ${CMAKE_CXX_FLAGS}" )
endif()
涉及知识点 | 知识点介绍 |
---|---|
CMAKE_COMPILER_IS_GNUCXX | 如果C++(CXX)编译器是GNU则为True |
GCC优化选项 | gcc提供了为了满足用户不同程度的的优化需要,提供了近百种优化选项,用来对{编译时间,目标文件长度,执行效率}这个三维模型进行不同的取舍和平衡。优化的方法不一而足,总体上将有以下几类:1)精简操作指令;2)尽量满足cpu的流水操作;3)通过对程序行为地猜测,重新调整代码的执行顺序;4)充分使用寄存器;5)对简单的调用进行展开等等。 而上面代码中的**-ffloat-store**:不要在寄存器中存放浮点变量 . 这样可以防止某些机器上不希望的过高精度 |
if( BUILD_SMALL_DEBUG_FILES )
set( CMAKE_C_FLAGS_DEBUG "-g1 -ggdb1" )
set( CMAKE_CXX_FLAGS_DEBUG "-g1 -ggdb1" )
else()
set( CMAKE_C_FLAGS_DEBUG "-g3 -ggdb3" )
set( CMAKE_CXX_FLAGS_DEBUG "-g3 -ggdb3" )
endif()
涉及知识点 | 知识点介绍 |
---|---|
CMAKE_ |
对于这种语言当执行时所需的标志。 -g1 -ggdb1或者-g3 -ggdb3: 调试生成时选择Level1提供最少的信息,但是生成的文件也最小。 选择Level3提供最全的信息,但是二进制文件则大的多。 |
if( KICAD_SANITIZE_ADDRESS )
add_definitions( -DKICAD_SANITIZE_ADDRESS )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_SANITIZE_VECTOR -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer" )
# ASAN shouldn't be used with these options (https://github.com/google/sanitizers/wiki/AddressSanitizer#faq)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-stack-protector -U_FORTIFY_SOURCE" )
endif()
使用AddressSanitizer选项构建KiCad。与gold linker不兼容
涉及知识点 | 知识点介绍 |
---|---|
AddressSanitizer | 该工具g++自带。它其实是一个内存错误检测工具,可以检测的问题主要有:内存泄漏、堆栈和全局内存越界访问、free后继续使用、局部内存被外层使用、初始化列表顺序错误。使用方法: 1. 用 -fsanitize=address 选项编译和链接你的程序。 2. 用 -fno-omit-frame-pointer 编译,以得到更容易理解stack trace。, 3. 要获得完美的堆栈跟踪,您可能需要禁用内联(只使用-O1)和尾部调用消除(-fno-optimize-sibling-call) 4. 检查栈对象使用超过定义范围的bug(-fsanitize-address-use-after-scope) |
stack-protector | gcc提供了栈保护机制stack-protector。关于stack-protector包含三个选项,分别是stack-protector、stack-protector-all、stack-protector-strong、stack-protector-explicit四种。 stack-protector:保护函数中通过alloca()分配缓存以及存在大于8字节的缓存。缺点是保护能力有限。 stack-protector-all:保护所有函数的栈。缺点是增加很多额外栈空间,增加程序体积。 stack-protector-strong:在stack-protector基础上,增加本地数组、指向本地帧栈地址空间保护。 stack-protector-explicit:在stack-protector基础上,增加程序中显式属性"stack_protect"空间。 |
FORTIFY_SOURCE | 启用-D/U_FORTIFY_SOURCE |
if( KICAD_SANITIZE_THREADS )
add_definitions( -DKICAD_SANITIZE_THREADS )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_SANITIZE_VECTOR -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer" )
# Based on this warning https://github.com/JuliaLang/julia/blob/29d5158d27ddc3983ae2e373c4cd05569b9ead6c/src/julia.h#L77
if( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11 )
message( WARNING "Clang version 11 and below may leak memory when running the thread sanitizer.\n"
"Be careful when using this compiler.")
endif()
# 复制上一节ASAN内容,因为为什么不呢
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-stack-protector -U_FORTIFY_SOURCE" )
endif()
使用AddressSanitizer选项构建KiCad。与gold linker不兼容
涉及知识点 | 知识点介绍 |
---|---|
ThreadSanitizer | ThreadSanitizer是一个检测数据竞争的工具。它由编译器检测模块和运行时库组成。ThreadSanitizer引入的典型减速是 5x-15x 左右。ThreadSanitizer引入的典型内存开销约为5x-10x。使用: 1. 只需用-fsanitize=thread编译并链接程序 2. -fno-optimize-sibling-calls作用请翻看上一节 3. -fno-omit-frame-pointer作用请翻看上一节 |
if( KICAD_STDLIB_DEBUG )
add_definitions( -DKICAD_STDLIB_DEBUG )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG" )
elseif( KICAD_STDLIB_LIGHT_DEBUG )
# useless if KICAD_STDLIB_DEBUG is ON.
# this option makes some controls to trap out of bound memory access.
add_definitions( -DKICAD_STDLIB_LIGHT_DEBUG )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wp,-D_GLIBCXX_ASSERTIONS" )
endif()
string在GLIBCXX_DEBUG宏是否存在的情况下处理方式不同,不同的库如果没带该选项而自己的项目又定义了它,有可能造成冲突导致程序挂掉,但是又想使程序项目在STL检测的庇护下,可以修改/usr/include/c++/4.7/debug/debug.h头文件,将#ifndef _GLIBCXX_DEBUG修改为#ifndef GLIBCXX_DEBUG,然后在自己的项目中定义_GLIBCXX_DEBUG_宏,绕开冲突即可。
使用-D_GLIBCXX_DEBUG命令进行编译
if( MINGW )
#给mingw_resource_compiler_INCLUDE_DIRS列表添加rc、可执行文件路径、KICAD_BUILD_ARCH值、DPI感知值。
#
list(APPEND mingw_resource_compiler_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/resources/msw/ )
# include dir to allow getting the version header
list(APPEND mingw_resource_compiler_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/ )
list(APPEND mingw_resource_compiler_DEFINES KICAD_BUILD_ARCH=${KICAD_BUILD_ARCH} )
if( KICAD_WIN32_DPI_AWARE )
list(APPEND mingw_resource_compiler_DEFINES KICAD_WIN32_DPI_AWARE=1 )
endif()
#
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" )
#预留一段代码:设为true则使response file 失效。
#从版本2.8.5开始,Cmake使用一个响应文件(.jsp),来传递include paths的列表给gcc。
#然而,在mingw32+msys模式下(mingw64不确定),至少需要gcc4.88和更新版本,这个文件不能正常展开,所以这种模式下,include paths就失效了。如果是这种情况,需要disable这个响应函数。
if( false ) #set to true to disable the include response file
if( WIN32 AND MSYS AND NOT CMAKE_CROSSCOMPILING )
# fixme: it is needed only with MSYS+MINGW32? or always under MINGW
if( ${CMAKE_SIZEOF_VOID_P} MATCHES 4 )
#禁掉response file
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 0 )
endif()
endif()
endif()
#cmake使用响应文件存储要发给archiver的对象列表。因为这个列表太长了,有可能产生错误 ,所以强制使用响应文件存储。
SET( CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1 )
#mingw编译器可以使用微软系统的snprintf作为标准输出,但是它和C99标准有一个坏的API,所以需要我们确保使用自己的snprintf
# snprintf
add_definitions(-D__USE_MINGW_ANSI_STDIO=1)
# Allow linking for Boost for the UUID against bcrypt
set( EXTRA_LIBS "bcrypt" )
endif()
#暂时不涉及苹果系统
if( APPLE )
set( CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -headerpad_max_install_names") # needed by fixbundle
endif()
endif( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
涉及知识点 | 知识点介绍 |
---|---|
list函数作用 | 其他list函数与append使用方法类似。见博客:Cmake中的list操作 |
snprintf函数 | sprintf函数、snprintf函数、asprintf函数、vsprintf |
CMAKE_EXE_LINKER_FLAGS_RELEASE | 未搞懂什么作用,待后续更新 |
用msvc编译暂时有问题,这段代码的解析后续更新
if( NOT APPLE )
#所有的路径如果开头不是“/”,则都是在CMAKE_INSTALL_PREFIX路径下
set( KICAD_BIN bin CACHE PATH "Location of KiCad binaries." )
# Do not make these variables "PATH" b/c cmake will truncate them and we need the full path
if( NOT IS_ABSOLUTE ${CMAKE_INSTALL_DATADIR} )
#设置Kicad data文件路径
set( KICAD_DATA ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/kicad CACHE STRING "Location of KiCad data files." )
#设置Kicad 文档文件路径
set( KICAD_DOCS ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/doc/kicad CACHE STRING "Location of KiCad documentation files." )
else()
set( KICAD_DATA ${CMAKE_INSTALL_DATADIR}/kicad CACHE STRING "Location of KiCad data files." )
set( KICAD_DOCS ${CMAKE_INSTALL_DATADIR}/doc/kicad CACHE STRING "Location of KiCad documentation files." )
endif()
set( KICAD_LIBRARY_DATA ${KICAD_DATA}
CACHE STRING "Location of KiCad stock EDA library data" )
if( WIN32 )
set( KICAD_PLUGINS ${KICAD_BIN}/scripting/plugins CACHE PATH "Location of KiCad plugins." )
set( KICAD_LIB ${KICAD_BIN} CACHE PATH "Location of KiCad shared objects" )
set( KICAD_USER_PLUGIN ${KICAD_BIN}/plugins CACHE PATH "Location of KiCad user-loaded plugins" )
else()
set( KICAD_PLUGINS ${KICAD_DATA}/plugins CACHE PATH "Location of KiCad plugins." )
set( KICAD_LIB ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Location of KiCad shared objects" )
set( KICAD_USER_PLUGIN ${CMAKE_INSTALL_LIBDIR}/kicad/plugins CACHE PATH "Location of KiCad user-loaded plugins" )
endif()
set( KICAD_DEMOS ${KICAD_DATA}/demos
CACHE PATH "Location of KiCad demo files." )
set( KICAD_TEMPLATE ${KICAD_LIBRARY_DATA}/template
CACHE PATH "Location of KiCad template files." )
else()
#此处为APPLE配置,此时还不需解析,后续更新
endif()
mark_as_advanced( KICAD_BIN
KICAD_PLUGINS
KICAD_USER_PLUGIN
KICAD_LIB
KICAD_DATA
KICAD_LIBRARY_DATA
KICAD_DOCS
KICAD_DEMOS
KICAD_TEMPLATE )
#调用本项目中的Functions.cmake(函数生成器,是调用TokenList2DsnLexer.cmake的标准方法)
include( Functions )
include( ExternalProject )
涉及知识点 | 知识点介绍 |
---|---|
KICAD_BIN | KICAD_BIN = bin: 安装时各类exe、dll等二进制可执行文件。 |
KICAD_PLUGINS | 放Kicad脚本插件的地方。默认放了一些从eeschema读取网表文件生成bom的一些脚本。 |
KICAD_USERS_PLUGINS | 放用户Kicad插件的地方:默认的只有一种:3d查看器。 |
KICAD_LiB | 放置生成的dll的地方。 |
KICAD_DATA | Kicad 所需的数据。包括3个文件夹: demos示例工程; resources图片icon; template工程模板。 |
KICAD_LIBRARY_DATA | Location of KiCad stock EDA library data。详细解释,后续更新 |
KICAD_DOCS | Location of KiCad documentation files.详细解释,后续更新 |
KICAD_DEMOS | 存储项目示例的路径 |
KICAD_TEMPLATE | 模板文件的路径 |
全部代码太长,以GLM库为例子进行介绍。
##########################################
#查找GLM库
##########################################
find_package( GLM 0.9.8 REQUIRED )
add_definitions( -DGLM_FORCE_CTOR_INIT )
check_find_package_result( GLM_FOUND "GLM" )
include_directories( SYSTEM ${GLM_INCLUDE_DIR} )
涉及知识点 | 知识点介绍 |
---|---|
find_package | CMake 会到变量 CMAKE_MODULE_PATH 指示的目录中查找下查找Findxxx.cmake文件,然后在cmake安装目录下module文件夹下查找Findxxx.cmake文件。会自动给一系列变量赋值: Once done this will define:: GLM_FOUND - system has GLM GLM_INCLUDE_DIR - the GLM include directory GLM_LIBRARIES - Link these to use GLM GLM_NEED_PREFIX - this is set if the functions are prefixed with GLM GLM_VERSION_STRING - the version of GLM found (since CMake 2.8.8) |
check_find_package_result | CMAKE_MODULE_PATH(即CMakeModules目录)下CheckFindPackageResult.cmake文件 |
include_directories | include_directories是用来提供找头文件路径的,打个比方,我现在想要#include"cv.h",但是这个cv.h的路径是/usr/local/include/opencv。include_directories(/usr/local/include)来让库文件搜索以/usr/local/include为基础,即在main函数前写上#include “opencv/cv.h"即可 |
configure_file( ${PROJECT_SOURCE_DIR}/CMakeModules/config.h.cmake
${CMAKE_BINARY_DIR}/config.h )
涉及知识点 | 知识点介绍 |
---|---|
configure_file | 复制一份输入文件到输出文件,替换输入文件中被@VAR@或者${VAR}引用的变量值。也就是说,让普通文件,也能使用CMake中的变量。 |
if( KICAD_MAKE_LINK_MAPS )
# Currently only works on linux/gcc
if( UNIX AND NOT APPLE )
set( MAKE_LINK_MAPS true )
else()
set( MAKE_LINK_MAPS false )
endif()
endif()
目前只在linux/gcc环境下实现。
#================================================
# "make uninstall"
#================================================
#生成卸载文件:cmake_uninstall.cmake
configure_file(
"${CMAKE_MODULE_PATH}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY )
add_custom_target( uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" )
涉及知识点 | 知识点介绍 |
---|---|
add_custom_target | 增加一个没有输出的目标,使得它总是被构建。作者也还未搞太明白(后续更新) |
#================================================
# Installation
#================================================
###
# Install scripts
###
#如果在unix系统上,设置安装
if( UNIX AND NOT APPLE )
install( DIRECTORY scripts
DESTINATION ${KICAD_DOCS}
COMPONENT resources
PATTERN "*.bat" EXCLUDE
)
endif()
include( CTest )
enable_testing()
#如果在unix系统上,设置Cpack
if( UNIX AND NOT APPLE )
# Create a *.deb file:
set( CPACK_GENERATOR "DEB" )
set( CPACK_DEBIAN_PACKAGE_MAINTAINER "http://launchpad.net/kicad" )
set( CPACK_PACKAGE_VERSION_MAJOR 1 )
set( CPACK_PACKAGE_VERSION_MINOR 0 )
set( CPACK_PACKAGE_VERSION_PATCH 0 )
#set( CPACK_PACKAGE_CONTACT Firstname Lastname <email@company.com> )
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "KiCad built by CMake build system." )
include( CPack )
endif()
涉及知识点 | 知识点介绍 |
---|---|
add_custom_target | 增加一个没有输出的目标,使得它总是被构建。作者也还未搞太明白(后续更新) |
install函数 | install(TARGETS MyLib EXPORT MyLibTargets LIBRARY DESTINATION lib # 动态库安装路径 ARCHIVE DESTINATION lib # 静态库安装路径 RUNTIME DESTINATION bin # 可执行文件安装路径 PUBLIC_HEADER DESTINATION include # 头文件安装路径 ) |
CTest | CTest是CMake集成的一个测试工具,在使用CMakeLists.txt文件编译工程的时候,CTest会自动configure、build、test和展现测试结果 CTest有两个模式: 模式一: 使用CMake configure 和 build工程,在CMakeLists.txt文件中,使用特殊的命令取创建tests。CTest用来执行那些测试 模式二: 使用CTest来执行一个script(这个script的语法必须和CMakeLists.txt相同),去控制整个程序的输出结果 enable_testing()执行后,才能执行add_test()函数。 |
add_test | add_test(NAME [WORKING_DIRECTORY dir] COMMAND 如果已经运行过了ENABLE_TESTING命令,这个命令将为当前路径添加一个测试目标。如果ENABLE_TESTING还没有运行过,该命令啥事都不做。测试是由测试子系统运行的,它会以指定的参数执行Exename文件。Exename或者是由该工程构建的可执行文件,也可以是系统上自带的任意可执行文件(比如tclsh) |
Cpack | C++ 工程大部分都是用 CMake 配置编译, 而 CPack 是 CMake 内置的工具,支持打包成多种格式的安装包。因为是 CMake 的内置工具,所以使用的方式也是通过在 CMakeLists.txt 配置参数,就能达到我们的需求。使用起来很方便,容易上手。 |
#================================================
执行子目录下的CmakeList
#================================================
# Binaries ( CMake targets )
add_subdirectory( resources )
add_subdirectory( thirdparty )
add_subdirectory( bitmaps_png )
add_subdirectory( libs )
add_subdirectory( common )
add_subdirectory( 3d-viewer )
add_subdirectory( eeschema )
add_subdirectory( gerbview )
add_subdirectory( pcbnew )
add_subdirectory( pagelayout_editor )
add_subdirectory( bitmap2component )
add_subdirectory( pcb_calculator )
add_subdirectory( plugins ) # 3D plugins must be built before kicad
add_subdirectory( cvpcb ) # must be after pcbnew
add_subdirectory( kicad ) # should follow pcbnew, eeschema
add_subdirectory( tools )
add_subdirectory( utils )
add_subdirectory( qa )
# Demos
if( KICAD_INSTALL_DEMOS )
add_subdirectory( demos )
endif ( KICAD_INSTALL_DEMOS )
# I18n Translations
if( KICAD_BUILD_I18N )
add_subdirectory( translation )
endif()
add_subdirectory( template )
涉及知识点 | 知识点介绍 |
---|---|
add_subdirectory | 添加一个子目录并构建该子目录。 |
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。