Files
makefile_cpp/cmake/cmake_md.html
2023-06-25 18:00:56 +08:00

3428 lines
268 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" href="style.css">
<style>
@font-face {
font-family: octicons-link;
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
}
.markdown-body .octicon {
display: inline-block;
fill: currentColor;
vertical-align: text-bottom;
}
.markdown-body .anchor {
float: left;
line-height: 1;
margin-left: -20px;
padding-right: 4px;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #1b1f23;
vertical-align: middle;
visibility: hidden;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
text-decoration: none;
}
.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
visibility: visible;
}
.markdown-body {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
color: #24292e;
line-height: 1.5;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.markdown-body .pl-c {
color: #6a737d;
}
.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
color: #005cc5;
}
.markdown-body .pl-e,
.markdown-body .pl-en {
color: #6f42c1;
}
.markdown-body .pl-s .pl-s1,
.markdown-body .pl-smi {
color: #24292e;
}
.markdown-body .pl-ent {
color: #22863a;
}
.markdown-body .pl-k {
color: #d73a49;
}
.markdown-body .pl-pds,
.markdown-body .pl-s,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sra,
.markdown-body .pl-sr .pl-sre {
color: #032f62;
}
.markdown-body .pl-smw,
.markdown-body .pl-v {
color: #e36209;
}
.markdown-body .pl-bu {
color: #b31d28;
}
.markdown-body .pl-ii {
background-color: #b31d28;
color: #fafbfc;
}
.markdown-body .pl-c2 {
background-color: #d73a49;
color: #fafbfc;
}
.markdown-body .pl-c2:before {
content: "^M";
}
.markdown-body .pl-sr .pl-cce {
color: #22863a;
font-weight: 700;
}
.markdown-body .pl-ml {
color: #735c0f;
}
.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
color: #005cc5;
font-weight: 700;
}
.markdown-body .pl-mi {
color: #24292e;
font-style: italic;
}
.markdown-body .pl-mb {
color: #24292e;
font-weight: 700;
}
.markdown-body .pl-md {
background-color: #ffeef0;
color: #b31d28;
}
.markdown-body .pl-mi1 {
background-color: #f0fff4;
color: #22863a;
}
.markdown-body .pl-mc {
background-color: #ffebda;
color: #e36209;
}
.markdown-body .pl-mi2 {
background-color: #005cc5;
color: #f6f8fa;
}
.markdown-body .pl-mdr {
color: #6f42c1;
font-weight: 700;
}
.markdown-body .pl-ba {
color: #586069;
}
.markdown-body .pl-sg {
color: #959da5;
}
.markdown-body .pl-corl {
color: #032f62;
text-decoration: underline;
}
.markdown-body details {
display: block;
}
.markdown-body summary {
display: list-item;
}
.markdown-body a {
background-color: transparent;
}
.markdown-body a:active,
.markdown-body a:hover {
outline-width: 0;
}
.markdown-body strong {
font-weight: inherit;
font-weight: bolder;
}
.markdown-body h1 {
font-size: 2em;
margin: .67em 0;
}
.markdown-body img {
border-style: none;
}
.markdown-body code,
.markdown-body kbd,
.markdown-body pre {
font-family: monospace,monospace;
font-size: 1em;
}
.markdown-body hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
.markdown-body input {
font: inherit;
margin: 0;
}
.markdown-body input {
overflow: visible;
}
.markdown-body [type=checkbox] {
box-sizing: border-box;
padding: 0;
}
.markdown-body * {
box-sizing: border-box;
}
.markdown-body input {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
.markdown-body a {
color: #0366d6;
text-decoration: none;
}
.markdown-body a:hover {
text-decoration: underline;
}
.markdown-body strong {
font-weight: 600;
}
.markdown-body hr {
background: transparent;
border: 0;
border-bottom: 1px solid #dfe2e5;
height: 0;
margin: 15px 0;
overflow: hidden;
}
.markdown-body hr:before {
content: "";
display: table;
}
.markdown-body hr:after {
clear: both;
content: "";
display: table;
}
.markdown-body table {
border-collapse: collapse;
border-spacing: 0;
}
.markdown-body td,
.markdown-body th {
padding: 0;
}
.markdown-body details summary {
cursor: pointer;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-bottom: 0;
margin-top: 0;
}
.markdown-body h1 {
font-size: 32px;
}
.markdown-body h1,
.markdown-body h2 {
font-weight: 600;
}
.markdown-body h2 {
font-size: 24px;
}
.markdown-body h3 {
font-size: 20px;
}
.markdown-body h3,
.markdown-body h4 {
font-weight: 600;
}
.markdown-body h4 {
font-size: 16px;
}
.markdown-body h5 {
font-size: 14px;
}
.markdown-body h5,
.markdown-body h6 {
font-weight: 600;
}
.markdown-body h6 {
font-size: 12px;
}
.markdown-body p {
margin-bottom: 10px;
margin-top: 0;
}
.markdown-body blockquote {
margin: 0;
}
.markdown-body ol,
.markdown-body ul {
margin-bottom: 0;
margin-top: 0;
padding-left: 0;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: lower-roman;
}
.markdown-body ol ol ol,
.markdown-body ol ul ol,
.markdown-body ul ol ol,
.markdown-body ul ul ol {
list-style-type: lower-alpha;
}
.markdown-body dd {
margin-left: 0;
}
.markdown-body code,
.markdown-body pre {
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
font-size: 12px;
}
.markdown-body pre {
margin-bottom: 0;
margin-top: 0;
}
.markdown-body input::-webkit-inner-spin-button,
.markdown-body input::-webkit-outer-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
.markdown-body .border {
border: 1px solid #e1e4e8!important;
}
.markdown-body .border-0 {
border: 0!important;
}
.markdown-body .border-bottom {
border-bottom: 1px solid #e1e4e8!important;
}
.markdown-body .rounded-1 {
border-radius: 3px!important;
}
.markdown-body .bg-white {
background-color: #fff!important;
}
.markdown-body .bg-gray-light {
background-color: #fafbfc!important;
}
.markdown-body .text-gray-light {
color: #6a737d!important;
}
.markdown-body .mb-0 {
margin-bottom: 0!important;
}
.markdown-body .my-2 {
margin-bottom: 8px!important;
margin-top: 8px!important;
}
.markdown-body .pl-0 {
padding-left: 0!important;
}
.markdown-body .py-0 {
padding-bottom: 0!important;
padding-top: 0!important;
}
.markdown-body .pl-1 {
padding-left: 4px!important;
}
.markdown-body .pl-2 {
padding-left: 8px!important;
}
.markdown-body .py-2 {
padding-bottom: 8px!important;
padding-top: 8px!important;
}
.markdown-body .pl-3,
.markdown-body .px-3 {
padding-left: 16px!important;
}
.markdown-body .px-3 {
padding-right: 16px!important;
}
.markdown-body .pl-4 {
padding-left: 24px!important;
}
.markdown-body .pl-5 {
padding-left: 32px!important;
}
.markdown-body .pl-6 {
padding-left: 40px!important;
}
.markdown-body .f6 {
font-size: 12px!important;
}
.markdown-body .lh-condensed {
line-height: 1.25!important;
}
.markdown-body .text-bold {
font-weight: 600!important;
}
.markdown-body:before {
content: "";
display: table;
}
.markdown-body:after {
clear: both;
content: "";
display: table;
}
.markdown-body>:first-child {
margin-top: 0!important;
}
.markdown-body>:last-child {
margin-bottom: 0!important;
}
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
}
.markdown-body blockquote,
.markdown-body dl,
.markdown-body ol,
.markdown-body p,
.markdown-body pre,
.markdown-body table,
.markdown-body ul {
margin-bottom: 16px;
margin-top: 0;
}
.markdown-body hr {
background-color: #e1e4e8;
border: 0;
height: .25em;
margin: 24px 0;
padding: 0;
}
.markdown-body blockquote {
border-left: .25em solid #dfe2e5;
color: #6a737d;
padding: 0 1em;
}
.markdown-body blockquote>:first-child {
margin-top: 0;
}
.markdown-body blockquote>:last-child {
margin-bottom: 0;
}
.markdown-body kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
border-bottom-color: #959da5;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #959da5;
color: #444d56;
display: inline-block;
font-size: 11px;
line-height: 10px;
padding: 3px 5px;
vertical-align: middle;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
font-weight: 600;
line-height: 1.25;
margin-bottom: 16px;
margin-top: 24px;
}
.markdown-body h1 {
font-size: 2em;
}
.markdown-body h1,
.markdown-body h2 {
border-bottom: 1px solid #eaecef;
padding-bottom: .3em;
}
.markdown-body h2 {
font-size: 1.5em;
}
.markdown-body h3 {
font-size: 1.25em;
}
.markdown-body h4 {
font-size: 1em;
}
.markdown-body h5 {
font-size: .875em;
}
.markdown-body h6 {
color: #6a737d;
font-size: .85em;
}
.markdown-body ol,
.markdown-body ul {
padding-left: 2em;
}
.markdown-body ol ol,
.markdown-body ol ul,
.markdown-body ul ol,
.markdown-body ul ul {
margin-bottom: 0;
margin-top: 0;
}
.markdown-body li {
word-wrap: break-all;
}
.markdown-body li>p {
margin-top: 16px;
}
.markdown-body li+li {
margin-top: .25em;
}
.markdown-body dl {
padding: 0;
}
.markdown-body dl dt {
font-size: 1em;
font-style: italic;
font-weight: 600;
margin-top: 16px;
padding: 0;
}
.markdown-body dl dd {
margin-bottom: 16px;
padding: 0 16px;
}
.markdown-body table {
display: block;
overflow: auto;
width: 100%;
}
.markdown-body table th {
font-weight: 600;
}
.markdown-body table td,
.markdown-body table th {
border: 1px solid #dfe2e5;
padding: 6px 13px;
}
.markdown-body table tr {
background-color: #fff;
border-top: 1px solid #c6cbd1;
}
.markdown-body table tr:nth-child(2n) {
background-color: #f6f8fa;
}
.markdown-body img {
background-color: #fff;
box-sizing: content-box;
max-width: 100%;
}
.markdown-body img[align=right] {
padding-left: 20px;
}
.markdown-body img[align=left] {
padding-right: 20px;
}
.markdown-body code {
background-color: rgba(27,31,35,.05);
border-radius: 3px;
font-size: 85%;
margin: 0;
padding: .2em .4em;
}
.markdown-body pre {
word-wrap: normal;
}
.markdown-body pre>code {
background: transparent;
border: 0;
font-size: 100%;
margin: 0;
padding: 0;
white-space: pre;
word-break: normal;
}
.markdown-body .highlight {
margin-bottom: 16px;
}
.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.markdown-body .highlight pre,
.markdown-body pre {
background-color: #f6f8fa;
border-radius: 3px;
font-size: 85%;
line-height: 1.45;
overflow: auto;
padding: 16px;
}
.markdown-body pre code {
background-color: transparent;
border: 0;
display: inline;
line-height: inherit;
margin: 0;
max-width: auto;
overflow: visible;
padding: 0;
word-wrap: normal;
}
.markdown-body .commit-tease-sha {
color: #444d56;
display: inline-block;
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
font-size: 90%;
}
.markdown-body .blob-wrapper {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
overflow-x: auto;
overflow-y: hidden;
}
.markdown-body .blob-wrapper-embedded {
max-height: 240px;
overflow-y: auto;
}
.markdown-body .blob-num {
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
color: rgba(27,31,35,.3);
cursor: pointer;
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
font-size: 12px;
line-height: 20px;
min-width: 50px;
padding-left: 10px;
padding-right: 10px;
text-align: right;
user-select: none;
vertical-align: top;
white-space: nowrap;
width: 1%;
}
.markdown-body .blob-num:hover {
color: rgba(27,31,35,.6);
}
.markdown-body .blob-num:before {
content: attr(data-line-number);
}
.markdown-body .blob-code {
line-height: 20px;
padding-left: 10px;
padding-right: 10px;
position: relative;
vertical-align: top;
}
.markdown-body .blob-code-inner {
color: #24292e;
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
font-size: 12px;
overflow: visible;
white-space: pre;
word-wrap: normal;
}
.markdown-body .pl-token.active,
.markdown-body .pl-token:hover {
background: #ffea7f;
cursor: pointer;
}
.markdown-body kbd {
background-color: #fafbfc;
border: 1px solid #d1d5da;
border-bottom-color: #c6cbd1;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #c6cbd1;
color: #444d56;
display: inline-block;
font: 11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
line-height: 10px;
padding: 3px 5px;
vertical-align: middle;
}
.markdown-body :checked+.radio-label {
border-color: #0366d6;
position: relative;
z-index: 1;
}
.markdown-body .tab-size[data-tab-size="1"] {
-moz-tab-size: 1;
tab-size: 1;
}
.markdown-body .tab-size[data-tab-size="2"] {
-moz-tab-size: 2;
tab-size: 2;
}
.markdown-body .tab-size[data-tab-size="3"] {
-moz-tab-size: 3;
tab-size: 3;
}
.markdown-body .tab-size[data-tab-size="4"] {
-moz-tab-size: 4;
tab-size: 4;
}
.markdown-body .tab-size[data-tab-size="5"] {
-moz-tab-size: 5;
tab-size: 5;
}
.markdown-body .tab-size[data-tab-size="6"] {
-moz-tab-size: 6;
tab-size: 6;
}
.markdown-body .tab-size[data-tab-size="7"] {
-moz-tab-size: 7;
tab-size: 7;
}
.markdown-body .tab-size[data-tab-size="8"] {
-moz-tab-size: 8;
tab-size: 8;
}
.markdown-body .tab-size[data-tab-size="9"] {
-moz-tab-size: 9;
tab-size: 9;
}
.markdown-body .tab-size[data-tab-size="10"] {
-moz-tab-size: 10;
tab-size: 10;
}
.markdown-body .tab-size[data-tab-size="11"] {
-moz-tab-size: 11;
tab-size: 11;
}
.markdown-body .tab-size[data-tab-size="12"] {
-moz-tab-size: 12;
tab-size: 12;
}
.markdown-body .task-list-item {
list-style-type: none;
}
.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}
.markdown-body .task-list-item input {
margin: 0 .2em .25em -1.6em;
vertical-align: middle;
}
.markdown-body hr {
border-bottom-color: #eee;
}
.markdown-body .pl-0 {
padding-left: 0!important;
}
.markdown-body .pl-1 {
padding-left: 4px!important;
}
.markdown-body .pl-2 {
padding-left: 8px!important;
}
.markdown-body .pl-3 {
padding-left: 16px!important;
}
.markdown-body .pl-4 {
padding-left: 24px!important;
}
.markdown-body .pl-5 {
padding-left: 32px!important;
}
.markdown-body .pl-6 {
padding-left: 40px!important;
}
.markdown-body .pl-7 {
padding-left: 48px!important;
}
.markdown-body .pl-8 {
padding-left: 64px!important;
}
.markdown-body .pl-9 {
padding-left: 80px!important;
}
.markdown-body .pl-10 {
padding-left: 96px!important;
}
.markdown-body .pl-11 {
padding-left: 112px!important;
}
.markdown-body .pl-12 {
padding-left: 128px!important;
}
/*# sourceURL=webpack://./node_modules/github-markdown-css/github-markdown.css */
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9naXRodWItbWFya2Rvd24tY3NzL2dpdGh1Yi1tYXJrZG93bi5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFDRSwwQkFBMEI7RUFDMUIsMkRBQXF0RTtBQUN2dEU7O0FBRUE7RUFDRSxxQkFBcUI7RUFDckIsa0JBQWtCO0VBQ2xCLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxjQUFjO0VBQ2Qsa0JBQWtCO0VBQ2xCLGtCQUFrQjtBQUNwQjs7QUFFQTtFQUNFLGFBQWE7QUFDZjs7QUFFQTs7Ozs7O0VBTUUsY0FBYztFQUNkLHNCQUFzQjtFQUN0QixrQkFBa0I7QUFDcEI7O0FBRUE7Ozs7OztFQU1FLHFCQUFxQjtBQUN2Qjs7QUFFQTs7Ozs7O0VBTUUsbUJBQW1CO0FBQ3JCOztBQUVBO0VBQ0UsMEJBQTBCO0VBQzFCLDhCQUE4QjtFQUM5QixjQUFjO0VBQ2QsZ0JBQWdCO0VBQ2hCLGtJQUFrSTtFQUNsSSxlQUFlO0VBQ2YsZ0JBQWdCO0VBQ2hCLHFCQUFxQjtBQUN2Qjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7O0VBRUUsY0FBYztBQUNoQjs7QUFFQTs7RUFFRSxjQUFjO0FBQ2hCOztBQUVBOztFQUVFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTs7Ozs7OztFQU9FLGNBQWM7QUFDaEI7O0FBRUE7O0VBRUUsY0FBYztBQUNoQjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSx5QkFBeUI7RUFDekIsY0FBYztBQUNoQjs7QUFFQTtFQUNFLHlCQUF5QjtFQUN6QixjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsYUFBYTtBQUNmOztBQUVBO0VBQ0UsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7OztFQUdFLGNBQWM7RUFDZCxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxjQUFjO0VBQ2Qsa0JBQWtCO0FBQ3BCOztBQUVBO0VBQ0UsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTtFQUNFLHlCQUF5QjtFQUN6QixjQUFjO0FBQ2hCOztBQUVBO0VBQ0UseUJBQXlCO0VBQ3pCLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSx5QkFBeUI7RUFDekIsY0FBYztBQUNoQjs7QUFFQTtFQUNFLHlCQUF5QjtFQUN6QixjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsY0FBYztFQUNkLDBCQUEwQjtBQUM1Qjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxrQkFBa0I7QUFDcEI7O0FBRUE7RUFDRSw2QkFBNkI7QUFDL0I7O0FBRUE7O0VBRUUsZ0JBQWdCO0FBQ2xCOztBQUVBO0VBQ0Usb0JBQW9CO0VBQ3BCLG1CQUFtQjtBQUNyQjs7QUFFQTtFQUNFLGNBQWM7RUFDZCxlQUFlO0FBQ2pCOztBQUVBO0VBQ0Usa0JBQWtCO0FBQ3BCOztBQUVBOzs7RUFHRSxnQ0FBZ0M7RUFDaEMsY0FBYztBQUNoQjs7QUFFQTtFQUNFLHVCQUF1QjtFQUN2QixTQUFTO0VBQ1QsaUJBQWlCO0FBQ25COztBQUVBO0VBQ0UsYUFBYTtFQUNiLFNBQVM7QUFDWDs7QUFFQTtFQUNFLGlCQUFpQjtBQUNuQjs7QUFFQTtFQUNFLHNCQUFzQjtFQUN0QixVQUFVO0FBQ1o7O0FBRUE7RUFDRSxzQkFBc0I7QUFDeEI7O0FBRUE7RUFDRSxvQkFBb0I7RUFDcEIsa0JBQWtCO0VBQ2xCLG9CQUFvQjtBQUN0Qjs7QUFFQTtFQUNFLGNBQWM7RUFDZCxxQkFBcUI7QUFDdkI7O0FBRUE7RUFDRSwwQkFBMEI7QUFDNUI7O0FBRUE7RUFDRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSx1QkFBdUI7RUFDdkIsU0FBUztFQUNULGdDQUFnQztFQUNoQyxTQUFTO0VBQ1QsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsV0FBVztFQUNYLFdBQVc7RUFDWCxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UseUJBQXlCO0VBQ3pCLGlCQUFpQjtBQUNuQjs7QUFFQTs7RUFFRSxVQUFVO0FBQ1o7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBOzs7Ozs7RUFNRSxnQkFBZ0I7RUFDaEIsYUFBYTtBQUNmOztBQUVBO0VBQ0UsZUFBZTtBQUNqQjs7QUFFQTs7RUFFRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsZUFBZTtBQUNqQjs7QUFFQTs7RUFFRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsZUFBZTtBQUNqQjs7QUFFQTs7RUFFRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsbUJBQW1CO0VBQ25CLGFBQWE7QUFDZjs7QUFFQTtFQUNFLFNBQVM7QUFDWDs7QUFFQTs7RUFFRSxnQkFBZ0I7RUFDaEIsYUFBYTtFQUNiLGVBQWU7QUFDakI7O0FBRUE7O0VBRUUsNEJBQTRCO0FBQzlCOztBQUVBOzs7O0VBSUUsNEJBQTRCO0FBQzlCOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTs7RUFFRSw0RUFBNEU7RUFDNUUsZUFBZTtBQUNqQjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixhQUFhO0FBQ2Y7O0FBRUE7O0VBRUUsd0JBQXdCO0VBQ3hCLGdCQUFnQjtFQUNoQixTQUFTO0FBQ1g7O0FBRUE7RUFDRSxtQ0FBbUM7QUFDckM7O0FBRUE7RUFDRSxtQkFBbUI7QUFDckI7O0FBRUE7RUFDRSwwQ0FBMEM7QUFDNUM7O0FBRUE7RUFDRSw0QkFBNEI7QUFDOUI7O0FBRUE7RUFDRSxnQ0FBZ0M7QUFDbEM7O0FBRUE7RUFDRSxtQ0FBbUM7QUFDckM7O0FBRUE7RUFDRSx3QkFBd0I7QUFDMUI7O0FBRUE7RUFDRSwwQkFBMEI7QUFDNUI7O0FBRUE7RUFDRSw0QkFBNEI7RUFDNUIseUJBQXlCO0FBQzNCOztBQUVBO0VBQ0UseUJBQXlCO0FBQzNCOztBQUVBO0VBQ0UsMkJBQTJCO0VBQzNCLHdCQUF3QjtBQUMxQjs7QUFFQTtFQUNFLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLDZCQUE2QjtFQUM3QiwwQkFBMEI7QUFDNUI7O0FBRUE7O0VBRUUsNEJBQTRCO0FBQzlCOztBQUVBO0VBQ0UsNkJBQTZCO0FBQy9COztBQUVBO0VBQ0UsNEJBQTRCO0FBQzlCOztBQUVBO0VBQ0UsNEJBQTRCO0FBQzlCOztBQUVBO0VBQ0UsNEJBQTRCO0FBQzlCOztBQUVBO0VBQ0UseUJBQXlCO0FBQzNCOztBQUVBO0VBQ0UsMkJBQTJCO0FBQzdCOztBQUVBO0VBQ0UsMEJBQTBCO0FBQzVCOztBQUVBO0VBQ0UsV0FBVztFQUNYLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxXQUFXO0VBQ1gsV0FBVztFQUNYLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSx1QkFBdUI7QUFDekI7O0FBRUE7RUFDRSwwQkFBMEI7QUFDNUI7O0FBRUE7RUFDRSxjQUFjO0VBQ2QscUJBQXFCO0FBQ3ZCOztBQUVBOzs7Ozs7O0VBT0UsbUJBQW1CO0VBQ25CLGFBQWE7QUFDZjs7QUFFQTtFQUNFLHlCQUF5QjtFQUN6QixTQUFTO0VBQ1QsYUFBYTtFQUNiLGNBQWM7RUFDZCxVQUFVO0FBQ1o7O0FBRUE7RUFDRSxnQ0FBZ0M7RUFDaEMsY0FBYztFQUNkLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxhQUFhO0FBQ2Y7O0FBRUE7RUFDRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSx5QkFBeUI7RUFDekIseUJBQXlCO0VBQ3pCLDRCQUE0QjtFQUM1QixrQkFBa0I7RUFDbEIsa0NBQWtDO0VBQ2xDLGNBQWM7RUFDZCxxQkFBcUI7RUFDckIsZUFBZTtFQUNmLGlCQUFpQjtFQUNqQixnQkFBZ0I7RUFDaEIsc0JBQXNCO0FBQ3hCOztBQUVBOzs7Ozs7RUFNRSxnQkFBZ0I7RUFDaEIsaUJBQWlCO0VBQ2pCLG1CQUFtQjtFQUNuQixnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBOztFQUVFLGdDQUFnQztFQUNoQyxvQkFBb0I7QUFDdEI7O0FBRUE7RUFDRSxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxpQkFBaUI7QUFDbkI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsaUJBQWlCO0FBQ25COztBQUVBO0VBQ0UsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTs7RUFFRSxpQkFBaUI7QUFDbkI7O0FBRUE7Ozs7RUFJRSxnQkFBZ0I7RUFDaEIsYUFBYTtBQUNmOztBQUVBO0VBQ0Usb0JBQW9CO0FBQ3RCOztBQUVBO0VBQ0UsZ0JBQWdCO0FBQ2xCOztBQUVBO0VBQ0UsaUJBQWlCO0FBQ25COztBQUVBO0VBQ0UsVUFBVTtBQUNaOztBQUVBO0VBQ0UsY0FBYztFQUNkLGtCQUFrQjtFQUNsQixnQkFBZ0I7RUFDaEIsZ0JBQWdCO0VBQ2hCLFVBQVU7QUFDWjs7QUFFQTtFQUNFLG1CQUFtQjtFQUNuQixlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsY0FBYztFQUNkLGNBQWM7RUFDZCxXQUFXO0FBQ2I7O0FBRUE7RUFDRSxnQkFBZ0I7QUFDbEI7O0FBRUE7O0VBRUUseUJBQXlCO0VBQ3pCLGlCQUFpQjtBQUNuQjs7QUFFQTtFQUNFLHNCQUFzQjtFQUN0Qiw2QkFBNkI7QUFDL0I7O0FBRUE7RUFDRSx5QkFBeUI7QUFDM0I7O0FBRUE7RUFDRSxzQkFBc0I7RUFDdEIsdUJBQXVCO0VBQ3ZCLGVBQWU7QUFDakI7O0FBRUE7RUFDRSxrQkFBa0I7QUFDcEI7O0FBRUE7RUFDRSxtQkFBbUI7QUFDckI7O0FBRUE7RUFDRSxvQ0FBb0M7RUFDcEMsa0JBQWtCO0VBQ2xCLGNBQWM7RUFDZCxTQUFTO0VBQ1Qsa0JBQWtCO0FBQ3BCOztBQUVBO0VBQ0UsaUJBQWlCO0FBQ25COztBQUVBO0VBQ0UsdUJBQXVCO0VBQ3ZCLFNBQVM7RUFDVCxlQUFlO0VBQ2YsU0FBUztFQUNULFVBQVU7RUFDVixnQkFBZ0I7RUFDaEIsa0JBQWtCO0FBQ3BCOztBQUVBO0VBQ0UsbUJBQW1CO0FBQ3JCOztBQUVBO0VBQ0UsZ0JBQWdCO0VBQ2hCLGtCQUFrQjtBQUNwQjs7QUFFQTs7RUFFRSx5QkFBeUI7RUFDekIsa0JBQWtCO0VBQ2xCLGNBQWM7RUFDZCxpQkFBaUI7RUFDakIsY0FBYztFQUNkLGFBQWE7QUFDZjs7QUFFQTtFQUNFLDZCQUE2QjtFQUM3QixTQUFTO0VBQ1QsZUFBZTtFQUNmLG9CQUFvQjtFQUNwQixTQUFTO0VBQ1QsZUFBZTtFQUNmLGlCQUFpQjtFQUNqQixVQUFVO0VBQ1YsaUJBQWlCO0FBQ25COztBQUVBO0VBQ0UsY0FBYztFQUNkLHFCQUFxQjtFQUNyQiw0RUFBNEU7RUFDNUUsY0FBYztBQUNoQjs7QUFFQTtFQUNFLDhCQUE4QjtFQUM5QiwrQkFBK0I7RUFDL0IsZ0JBQWdCO0VBQ2hCLGtCQUFrQjtBQUNwQjs7QUFFQTtFQUNFLGlCQUFpQjtFQUNqQixnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRSxzQkFBc0I7RUFDdEIscUJBQXFCO0VBQ3JCLHlCQUF5QjtFQUN6Qix3QkFBd0I7RUFDeEIsZUFBZTtFQUNmLDRFQUE0RTtFQUM1RSxlQUFlO0VBQ2YsaUJBQWlCO0VBQ2pCLGVBQWU7RUFDZixrQkFBa0I7RUFDbEIsbUJBQW1CO0VBQ25CLGlCQUFpQjtFQUNqQixpQkFBaUI7RUFDakIsbUJBQW1CO0VBQ25CLG1CQUFtQjtFQUNuQixTQUFTO0FBQ1g7O0FBRUE7RUFDRSx3QkFBd0I7QUFDMUI7O0FBRUE7RUFDRSwrQkFBK0I7QUFDakM7O0FBRUE7RUFDRSxpQkFBaUI7RUFDakIsa0JBQWtCO0VBQ2xCLG1CQUFtQjtFQUNuQixrQkFBa0I7RUFDbEIsbUJBQW1CO0FBQ3JCOztBQUVBO0VBQ0UsY0FBYztFQUNkLDRFQUE0RTtFQUM1RSxlQUFlO0VBQ2YsaUJBQWlCO0VBQ2pCLGdCQUFnQjtFQUNoQixpQkFBaUI7QUFDbkI7O0FBRUE7O0VBRUUsbUJBQW1CO0VBQ25CLGVBQWU7QUFDakI7O0FBRUE7RUFDRSx5QkFBeUI7RUFDekIseUJBQXlCO0VBQ3pCLDRCQUE0QjtFQUM1QixrQkFBa0I7RUFDbEIsa0NBQWtDO0VBQ2xDLGNBQWM7RUFDZCxxQkFBcUI7RUFDckIsMEVBQTBFO0VBQzFFLGlCQUFpQjtFQUNqQixnQkFBZ0I7RUFDaEIsc0JBQXNCO0FBQ3hCOztBQUVBO0VBQ0UscUJBQXFCO0VBQ3JCLGtCQUFrQjtFQUNsQixVQUFVO0FBQ1o7O0FBRUE7RUFDRSxnQkFBZ0I7RUFDaEIsV0FBVztBQUNiOztBQUVBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVc7QUFDYjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixXQUFXO0FBQ2I7O0FBRUE7RUFDRSxnQkFBZ0I7RUFDaEIsV0FBVztBQUNiOztBQUVBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVc7QUFDYjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixXQUFXO0FBQ2I7O0FBRUE7RUFDRSxnQkFBZ0I7RUFDaEIsV0FBVztBQUNiOztBQUVBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVc7QUFDYjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixXQUFXO0FBQ2I7O0FBRUE7RUFDRSxpQkFBaUI7RUFDakIsWUFBWTtBQUNkOztBQUVBO0VBQ0UsaUJBQWlCO0VBQ2pCLFlBQVk7QUFDZDs7QUFFQTtFQUNFLGlCQUFpQjtFQUNqQixZQUFZO0FBQ2Q7O0FBRUE7RUFDRSxxQkFBcUI7QUFDdkI7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsMkJBQTJCO0VBQzNCLHNCQUFzQjtBQUN4Qjs7QUFFQTtFQUNFLHlCQUF5QjtBQUMzQjs7QUFFQTtFQUNFLHlCQUF5QjtBQUMzQjs7QUFFQTtFQUNFLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDRCQUE0QjtBQUM5Qjs7QUFFQTtFQUNFLDZCQUE2QjtBQUMvQjs7QUFFQTtFQUNFLDZCQUE2QjtBQUMvQiIsInNvdXJjZVJvb3QiOiIifQ== */
</style>
<style>
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
/*# sourceURL=webpack://./node_modules/prismjs/themes/prism.css */
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9wcmlzbWpzL3RoZW1lcy9wcmlzbS5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7RUFJRTs7QUFFRjs7Q0FFQyxZQUFZO0NBQ1osZ0JBQWdCO0NBQ2hCLHdCQUF3QjtDQUN4QixzRUFBc0U7Q0FDdEUsY0FBYztDQUNkLGdCQUFnQjtDQUNoQixnQkFBZ0I7Q0FDaEIsb0JBQW9CO0NBQ3BCLGtCQUFrQjtDQUNsQixpQkFBaUI7Q0FDakIsZ0JBQWdCOztDQUVoQixnQkFBZ0I7Q0FDaEIsY0FBYztDQUNkLFdBQVc7O0NBRVgscUJBQXFCO0NBQ3JCLGtCQUFrQjtDQUNsQixpQkFBaUI7Q0FDakIsYUFBYTtBQUNkOztBQUVBOztDQUVDLGlCQUFpQjtDQUNqQixtQkFBbUI7QUFDcEI7O0FBRUE7O0NBRUMsaUJBQWlCO0NBQ2pCLG1CQUFtQjtBQUNwQjs7QUFFQTtDQUNDOztFQUVDLGlCQUFpQjtDQUNsQjtBQUNEOztBQUVBLGdCQUFnQjtBQUNoQjtDQUNDLFlBQVk7Q0FDWixjQUFjO0NBQ2QsY0FBYztBQUNmOztBQUVBOztDQUVDLG1CQUFtQjtBQUNwQjs7QUFFQSxnQkFBZ0I7QUFDaEI7Q0FDQyxhQUFhO0NBQ2IsbUJBQW1CO0NBQ25CLG1CQUFtQjtBQUNwQjs7QUFFQTs7OztDQUlDLGdCQUFnQjtBQUNqQjs7QUFFQTtDQUNDLFdBQVc7QUFDWjs7QUFFQTtDQUNDLFdBQVc7QUFDWjs7QUFFQTs7Ozs7OztDQU9DLFdBQVc7QUFDWjs7QUFFQTs7Ozs7O0NBTUMsV0FBVztBQUNaOztBQUVBOzs7OztDQUtDLGNBQWM7Q0FDZCxvRUFBb0U7Q0FDcEUsaUNBQWlDO0FBQ2xDOztBQUVBOzs7Q0FHQyxXQUFXO0FBQ1o7O0FBRUE7O0NBRUMsY0FBYztBQUNmOztBQUVBOzs7Q0FHQyxXQUFXO0FBQ1o7O0FBRUE7O0NBRUMsaUJBQWlCO0FBQ2xCO0FBQ0E7Q0FDQyxrQkFBa0I7QUFDbkI7O0FBRUE7Q0FDQyxZQUFZO0FBQ2IiLCJzb3VyY2VSb290IjoiIn0= */
</style>
<style>
</style>
<style>
.markdown-body {
font-family: -apple-system,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media not print {
.markdown-body {
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
}
.hf-container {
color: #24292e;
line-height: 1.3;
}
.markdown-body .highlight pre,
.markdown-body pre {
white-space: pre-wrap;
}
.markdown-body table {
display: table;
}
.markdown-body img[data-align="center"] {
display: block;
margin: 0 auto;
}
.markdown-body img[data-align="right"] {
display: block;
margin: 0 0 0 auto;
}
.markdown-body li.task-list-item {
list-style-type: none;
}
.markdown-body li > [type=checkbox] {
margin: 0 0 0 -1.3em;
}
.markdown-body input[type="checkbox"] ~ p {
margin-top: 0;
display: inline-block;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: decimal;
}
.markdown-body ol ol ol,
.markdown-body ol ul ol,
.markdown-body ul ol ol,
.markdown-body ul ul ol {
list-style-type: decimal;
}
</style>
<style>.markdown-body a.footnote-ref {
text-decoration: none;
}
.footnotes {
font-size: .85em;
opacity: .8;
}
.footnotes li[role="doc-endnote"] {
position: relative;
}
.footnotes .footnote-back {
position: absolute;
font-family: initial;
top: .2em;
right: 1em;
text-decoration: none;
}
.inline-math.invalid,
.multiple-math.invalid {
color: rgb(255, 105, 105);
}
.toc-container {
width: 100%;
}
.toc-container .toc-title {
font-weight: 700;
font-size: 1.2em;
margin-bottom: 0;
}
.toc-container li,
.toc-container ul,
.toc-container ul li {
list-style: none !important;
}
.toc-container > ul {
padding-left: 0;
}
.toc-container ul li span {
display : flex;
}
.toc-container ul li span a {
color: inherit;
text-decoration: none;
}
.toc-container ul li span a:hover {
color: inherit;
text-decoration: none;
}
.toc-container ul li span span.dots {
flex: 1;
height: 0.65em;
margin: 0 10px;
border-bottom: 2px dotted black;
}
/*# sourceURL=webpack://./src/muya/lib/assets/styles/exportStyle.css */
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL3NyYy9tdXlhL2xpYi9hc3NldHMvc3R5bGVzL2V4cG9ydFN0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLHFCQUFxQjtBQUN2Qjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixXQUFXO0FBQ2I7O0FBRUE7RUFDRSxrQkFBa0I7QUFDcEI7O0FBRUE7RUFDRSxrQkFBa0I7RUFDbEIsb0JBQW9CO0VBQ3BCLFNBQVM7RUFDVCxVQUFVO0VBQ1YscUJBQXFCO0FBQ3ZCOztBQUVBOztFQUVFLHlCQUF5QjtBQUMzQjs7QUFFQTtFQUNFLFdBQVc7QUFDYjs7QUFFQTtFQUNFLGdCQUFnQjtFQUNoQixnQkFBZ0I7RUFDaEIsZ0JBQWdCO0FBQ2xCOztBQUVBOzs7RUFHRSwyQkFBMkI7QUFDN0I7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTtFQUNFLGNBQWM7RUFDZCxxQkFBcUI7QUFDdkI7QUFDQTtFQUNFLGNBQWM7RUFDZCxxQkFBcUI7QUFDdkI7O0FBRUE7RUFDRSxPQUFPO0VBQ1AsY0FBYztFQUNkLGNBQWM7RUFDZCwrQkFBK0I7QUFDakMiLCJzb3VyY2VSb290IjoiIn0= */</style>
<style>.markdown-body{}pre.front-matter{display:none!important;}</style>
</head>
<body>
<article class="markdown-body"><div class="toc-container"><p class="toc-title">目录</p><ul class="toc-list"><li><span><a class="toc-h1" href="#预备知识">预备知识</a><span class="dots"></span></span><ul><li><span><a class="toc-h2" href="#cmake是什么">CMake是什么</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#环境搭建与学习准备">环境搭建与学习准备</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#前置条件">前置条件</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#ubuntu安装cmake">Ubuntu安装CMake</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#windows安装cmake">Windows安装CMake</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#学习材料">学习材料</a><span class="dots"></span></span></li></ul></li></ul></li><li><span><a class="toc-h1" href="#cmake-tutorial">CMake Tutorial</a><span class="dots"></span></span><ul><li><span><a class="toc-h2" href="#第一步-起点">第一步 起点</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1--最简单的cmake项目">练习1 最简单的CMake项目</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#练习2-指定c标准">练习2 指定C++标准</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#练习3-添加版本号和配置头文件">练习3 添加版本号和配置头文件</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第二步-加个库">第二步 加个库</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-创建库文件">练习1 创建库文件</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#练习2-库文件可选编译">练习2 库文件可选编译</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第三步-添加使用依赖">第三步 添加使用依赖</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-为库添加使用依赖">练习1 为库添加使用依赖</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第四步-生成器表达式">第四步 生成器表达式</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-用接口库设置c标准">练习1 用接口库设置C++标准</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#练习2-添加编译警告选项">练习2 添加编译警告选项</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第五步-安装与测试">第五步 安装与测试</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-安装规则">练习1 安装规则</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#练习2-测试支持">练习2 测试支持</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第六步-添加测试面板支持">第六步 添加测试面板支持</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-发送测试结果到测试面板">练习1 发送测试结果到测试面板</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第七步-添加系统特性检查">第七步 添加系统特性检查</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#练习1-评估依赖可用性">练习1 评估依赖可用性</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#第八步-添加自定义命令及用自定义命令生成文件">第八步 添加自定义命令及用自定义命令生成文件</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#第九步-打包安装程序">第九步 打包安装程序</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#第十步-选择静态链接库或动态链接库">第十步 选择静态链接库或动态链接库</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#第十一步-添加导出配置">第十一步 添加导出配置</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#第十二步-打包调试版和发行版">第十二步 打包调试版和发行版</a><span class="dots"></span></span></li><li><span><a class="toc-h2" href="#练习-cmake-gui的使用">练习 cmake-gui的使用</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h1" href="#cmake基础知识补充">CMake基础知识补充</a><span class="dots"></span></span><ul><li><span><a class="toc-h2" href="#cmake命令使用">CMake命令使用</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#创建项目构建系统">创建项目构建系统</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#构建项目">构建项目</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#安装">安装</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#运行脚本">运行脚本</a><span class="dots"></span></span></li><li><span><a class="toc-h3" href="#运行命令行工具">运行命令行工具</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h2" href="#cmake指令">CMake指令</a><span class="dots"></span></span><ul><li><span><a class="toc-h3" href="#脚本指令">脚本指令</a><span class="dots"></span></span><ul><li><span><a class="toc-h4" href="#message">message</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#变量定义与取消">变量定义与取消</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#条件判断">条件判断</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#循环">循环</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#字符串操作">字符串操作</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#列表操作">列表操作</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#数学表达式">数学表达式</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#系统信息查询">系统信息查询</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#函数">函数</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#宏定义">宏定义</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#configure_file">configure_file</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#文件操作">文件操作</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#路径操作">路径操作</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#文件查找">文件查找</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#find_package">find_package</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h3" href="#项目指令">项目指令</a><span class="dots"></span></span><ul><li><span><a class="toc-h4" href="#add_dependencies">add_dependencies</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#add_custom_target">add_custom_target</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#属性设置">属性设置</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#添加预编译定义">添加预编译定义</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#添加编译选项">添加编译选项</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#mark_as_advanced">mark_as_advanced</a><span class="dots"></span></span></li><li><span><a class="toc-h4" href="#target_sources">target_sources</a><span class="dots"></span></span></li></ul></li><li><span><a class="toc-h3" href="#生成器表达式">生成器表达式</a><span class="dots"></span></span></li></ul></li></ul></li><li><span><a class="toc-h1" href="#下一步">下一步</a><span class="dots"></span></span></li></ul></div><h1 class="atx" id="预备知识">预备知识</h1>
<h2 class="atx" id="cmake是什么">CMake是什么</h2>
<p>CMake是一个管理代码构建的工具。与平台和构建系统无关。最初CMake只用于生成不同版本的Makefile。现在CMake可以生成不同构建工具构建文件也可以生成不同IDE如Visual Studio、XCode的项目文件。</p>
<p>CMake也可以在一定程度上简化C/C++第三方库的引入与使用流程。</p>
<p>CMake主要用于构建C或C++程序,但是也可以用于其他语言程序的构建。</p>
<p>****&nbsp;</p>
<h2 class="atx" id="环境搭建与学习准备">环境搭建与学习准备</h2>
<h2 class="atx" id="前置条件">前置条件</h2>
<p>如果是用Linux学习需要先安装GCC、make等工具。Ubuntu上安装命令如下</p>
<pre><code class="fenced-code-block language-shell"><span class="token function">sudo</span> <span class="token function">apt</span> <span class="token function">install</span> gcc g++ <span class="token function">make</span></code></pre>
<p>&nbsp;</p>
<p>如果是用Windows需要先装有编译工具。建议安装MinGW环境进行学习用Visual Studio也可以但是用来学习cmake的话感觉有点笨重本课程用的编译工具是MinGW能和课程工具保持一致最好。</p>
<p>MinGW常用有以下两个版本选择其中一个即可。<strong>w64devkit提供的工具更多操作更接近Linux</strong>。所以推荐用w64devkit。</p>
<p>w64devkit<a href="https://github.com/skeeto/w64devkit/releases">https://github.com/skeeto/w64devkit/releases</a></p>
<p>mingw-builds<a href="https://github.com/niXman/mingw-builds-binaries/releases">https://github.com/niXman/mingw-builds-binaries/releases</a></p>
<blockquote>
<p>最好会GCC与Make的基本用法。但不会也没关系影响不大。</p>
</blockquote>
<p>&nbsp;</p>
<h3 class="atx" id="ubuntu安装cmake">Ubuntu安装CMake</h3>
<pre><code class="fenced-code-block language-shell"><span class="token function">sudo</span> <span class="token function">apt</span> <span class="token function">install</span> cmake</code></pre>
<p>&nbsp;</p>
<h3 class="atx" id="windows安装cmake">Windows安装CMake</h3>
<p>cmake官网<a href="https://cmake.org/">https://cmake.org/</a></p>
<p>下载安装包直接下载msi版本。安装时将添加到系统环境变量勾选。</p>
<p><img alt="" src="img/install.png"></p>
<p>安装完成之后测试</p>
<pre><code class="fenced-code-block language-shell">cmake --version</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="学习材料">学习材料</h3>
<p>1、官方文档<a href="https://cmake.org/cmake/help/latest/">https://cmake.org/cmake/help/latest/</a></p>
<p>2、tutorial代码<a href="https://cmake.org/cmake/help/latest/_downloads/987664e19bf1c78e58910f17f64df29f/cmake-3.26.4-tutorial-source.zip">https://cmake.org/cmake/help/latest/_downloads/987664e19bf1c78e58910f17f64df29f/cmake-3.26.4-tutorial-source.zip</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="cmake-tutorial">CMake Tutorial</h1>
<h2 class="atx" id="第一步-起点">第一步 起点</h2>
<h3 class="atx" id="练习1--最简单的cmake项目">练习1 最简单的CMake项目</h3>
<p><strong><code>CMakeLists.txt</code></strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 1: 设置CMake最低版本要求为 3.10</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 创建一个名为Tutorial的项目</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 为项目添加一个叫做 Tutorial 的可执行文件</span>
<span class="token comment"># Hint: 一定要指定源文件 tutorial.cxx</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>cmake_minimum_required</mark></p>
<p>用于指定所需cmake最低版本</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> &lt;版本号<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span></code></pre>
<p>如果当前使用的cmake版本低于所指定的版本则会报错并且终止执行。</p>
<p><mark>project</mark></p>
<p>指定项目名称</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>&lt;项目名<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例 指定项目名称为Tutorial</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial<span class="token punctuation">)</span></code></pre>
<p><mark>add_executable</mark></p>
<p>利用指定的源文件在项目中添加可执行文件</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法 源文件可以有多个,用空格隔开</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>&lt;可执行文件名<span class="token punctuation">&gt;</span> &lt;源文件列表<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例 可执行文件名为Tutorial用到的源文件为tutorial.cxx</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span></code></pre>
<p><mark>cmake命令常用执行方法</mark></p>
<pre><code class="fenced-code-block language-shell"><span class="token comment"># 用法</span>
cmake -G <span class="token operator">&lt;</span>生成器名称<span class="token operator">&gt;</span> <span class="token operator">&lt;</span>CMakeLists.txt所在的目录<span class="token operator">&gt;</span></code></pre>
<p>如果使用默认生成器,则-G这部分可以省略具体支持哪些生成器可以用cmake --help查看</p>
<blockquote>
<p>扩展设置环境变量CMAKE_GENERATOR可以指定默认生成器简化cmake命令的执行</p>
</blockquote>
<p>&nbsp;</p>
<p><strong>课后练习</strong></p>
<ol>
<li>自行准备一个或多个源文件多练习几遍cmake项目的创建与生成可执行文件流程直到能默写出CMakeLists.txt中的内容并且熟练通过cmake构建出可执行文件。</li>
<li>配置CMAKE_GENERATOR环境变量并修改不同值通过cmake --help命令查看该变量对默认Generator(生成器)的影响。</li>
<li>如果电脑上有多套环境或工具例如有MinGW与Visual Studio或CodeBlocks修改-G指定不同生成器尝试生成不同工具对应的项目。</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="练习2-指定c标准">练习2 指定C++标准</h3>
<p><strong><code>CMakeLists.txt</code></strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 1: 设置CMake最低版本要求为 3.10</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 创建一个名为Tutorial的项目</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial<span class="token punctuation">)</span>
<span class="token comment"># TODO 7: 用上面project命令将项目版本设为 1.0</span>
<span class="token comment"># TODO 6: 设置变量 CMAKE_CXX_STANDARD 为 11</span>
<span class="token comment"># CMAKE_CXX_STANDARD_REQUIRED 为 True</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">26</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span>
<span class="token comment"># TODO 8: 用 configure_file 复制 TutorialConfig.h.in 生成</span>
<span class="token comment"># TutorialConfig.h</span>
<span class="token comment"># TODO 3: 为项目添加一个叫做 Tutorial 的可执行文件</span>
<span class="token comment"># Hint: 一定要指定源文件 tutorial.cxx</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>set</mark></p>
<p>用于给变量设置值</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>&lt;变量名<span class="token punctuation">&gt;</span> &lt;变量值<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">26</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>SRC_DIR /home/src<span class="token punctuation">)</span></code></pre>
<p><mark>CMAKE_CXX_STANDARD</mark></p>
<p>变量用于指定C++标准</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法 截止2023/6 std_num∈{98,11,14,17,20,23,26}</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> &lt;std_num<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">17</span><span class="token punctuation">)</span></code></pre>
<blockquote>
<p>在C++中可以通过输出__cplusplus查看当前编译器所用的标准</p>
<table>
<thead>
<tr>
<th align="center">__cplusplus的值</th>
<th align="center">对应的C++标准</th>
</tr>
</thead>
<tbody><tr>
<td align="center">199711</td>
<td align="center">C++98</td>
</tr>
<tr>
<td align="center">201103</td>
<td align="center">C++11</td>
</tr>
<tr>
<td align="center">201402</td>
<td align="center">C++14</td>
</tr>
<tr>
<td align="center">201703</td>
<td align="center">C++17</td>
</tr>
<tr>
<td align="center">202002</td>
<td align="center">C++20</td>
</tr>
<tr>
<td align="center">202100</td>
<td align="center">C++23</td>
</tr>
</tbody></table>
</blockquote>
<p><mark>CMAKE_CXX_STANDARD_REQUIRED</mark></p>
<p>变量如果设置为True则通过CMAKE_CXX_STANDARD设置的C++标准是必需的如果编译器不支持该标准则会输出错误提示信息。如果不设置或者设置为False则CMAKE_CXX_STANDARD设置的C++标准不是必需的,如果编译器不支持对应的标准,则会使用上一个版本的标准进行编译。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>课后练习</strong></p>
<ol>
<li>在std_num∈{98,11,14,17,20,23,26}的范围内设置C++标准输出__cplusplus的值并观察规律。</li>
<li>设置std_num∉{98,11,14,17,20,23,26}的C++标准值观察cmake提示信息并输出__cplusplus的值总结其规律。</li>
<li>类比C++标准的指定查询文档或其他资料补充C语言标准指定方式并准备几个C语言源文件进行实验。</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="练习3-添加版本号和配置头文件">练习3 添加版本号和配置头文件</h3>
<p>有些时候需要让源代码能访问CMakeLIsts.txt当中的数据比如说在CMakeLists.txt中定义版本号之后希望能在源程序中对版本号进行输出。本节内容为如何让源代码中能访问CMakeLists.txt中的变量数据。</p>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 1: 设置CMake最低版本要求为 3.10</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 创建一个名为Tutorial的项目</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">11.25</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 7: 用上面project命令将项目版本设为 1.0</span>
<span class="token comment"># TODO 6: 设置变量 CMAKE_CXX_STANDARD 为 11</span>
<span class="token comment"># CMAKE_CXX_STANDARD_REQUIRED 为 True</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span>
<span class="token comment"># set(STR_TEST "Hello World")</span>
<span class="token comment"># TODO 8: 用 configure_file 复制 TutorialConfig.h.in 生成</span>
<span class="token comment"># TutorialConfig.h</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 为项目添加一个叫做 Tutorial 的可执行文件</span>
<span class="token comment"># Hint: 一定要指定源文件 tutorial.cxx</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 9: 用 target_include_directories 添加头文件搜索目录 ${PROJECT_BINARY_DIR}</span>
<span class="token comment"># PUBLIC PRIVATE INTERFACE</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p><code>TutorialConfig.h.in</code></p>
<pre><code class="fenced-code-block language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">Tutorial_VERSION_MAJOR</span> <span class="token expression">@Tutorial_VERSION_MAJOR@</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">Tutorial_VERSION_MINOR</span> <span class="token expression">@Tutorial_VERSION_MINOR@</span></span></code></pre>
<p><strong>要点</strong></p>
<p><mark>project第二种用法</mark></p>
<p>定义项目名和版本号</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">2.15</span><span class="token punctuation">)</span></code></pre>
<p><mark>configure_file</mark></p>
<p>将输入文件复制为输出文件并把其中的变量引用替换为CMakeLists.txt中定义的变量如果变量未定义则替换为空串。输入文件中的变量引用方式为**@@变量名@@<strong>或者</strong>${变量名}**。</p>
<p>输入文件默认路径为CMakeLists.txt所在的路径输出文件的路径默认为cmake生成文件所在的路径。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>&lt;inputfile<span class="token punctuation">&gt;</span> &lt;outputfile<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span></code></pre>
<p>在输入文件中,用宏定义的方式对变量进行定义</p>
<pre><code class="fenced-code-block language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">Tutorial_VERSION_MAJOR</span> <span class="token expression">@Tutorial_VERSION_MAJOR@</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">Tutorial_VERSION_MINOR</span> <span class="token expression">$<span class="token punctuation">{</span>Tutorial_VERSION_MINOR<span class="token punctuation">}</span></span></span>
<span class="token comment">// 因为CMakeLists.txt中定义的字符串都是裸的所以如果一个变量的值为字符串需要用双引号包起来</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">define</span> <span class="token macro-name">STR_VAR</span> <span class="token string">"@STR_VAR@"</span></span></code></pre>
<p>上述定义中@Tutorial_VERSION_MAJOR@、${Tutorial_VERSION_MINOR}、@STR_VAR@在输出文件中会被替换为CMakeLists.txt中定义的对应变量值。</p>
<p>&nbsp;</p>
<p><mark>target_include_directories</mark></p>
<p>给指定的目标添加头文件搜索路径。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span> &lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> &lt;dir1 dir2 ...<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p><mark>_VERSION_MAJOR</mark> </p>
<p>版本号第一个组成部分。该变量为cmake自动定义的一个变量不需要手动定义值来自于project的定义。其中为用<strong>project</strong>定义的项目名。</p>
<p>&nbsp;</p>
<p><mark>_VERSION_MINOR</mark></p>
<p>版本号第二个组成部分。该变量为cmake自动定义的一个变量不需要手动定义值来自于project的定义。其中为用<strong>project</strong>定义的项目名。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>课后练习</strong></p>
<p>①通过本节学习的内容访问更多CMakeLists.txt中的变量。</p>
<p>②自行探究一下<code>include_directories</code>的用法比较与target_include_directories的异同。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第二步-加个库">第二步 加个库</h2>
<h3 class="atx" id="练习1-创建库文件">练习1 创建库文件</h3>
<p>前面的练习当中创建了可执行文件。本节将学习如何创建库文件以及库文件的使用 。同时也将练习将一个项目划分为多个子目录的方法。</p>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span>
<span class="token comment"># TODO 7: Create a variable USE_MYMATH using option and set default to ON</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># TODO 8: Use list() and APPEND to create a list of optional libraries</span>
<span class="token comment"># called EXTRA_LIBS and a list of optional include directories called</span>
<span class="token comment"># EXTRA_INCLUDES. Add the MathFunctions library and source directory to</span>
<span class="token comment"># the appropriate lists.</span>
<span class="token comment">#</span>
<span class="token comment"># Only call add_subdirectory and only add MathFunctions specific values</span>
<span class="token comment"># to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true.</span>
<span class="token comment"># TODO 2: Use add_subdirectory() to add MathFunctions to this project</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values</span>
<span class="token comment"># in target_link_libraries.</span>
<span class="token comment"># TODO 3: Use target_link_libraries to link the library to our executable</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> MathFunctions<span class="token punctuation">)</span>
<span class="token comment"># TODO 4: Add MathFunctions to Tutorial's target_include_directories()</span>
<span class="token comment"># Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder!</span>
<span class="token comment"># TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values</span>
<span class="token comment"># in target_include_directories.</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_SOURCE_DIR</span><span class="token punctuation">}</span></span>/MathFunctions"</span>
<span class="token punctuation">)</span></code></pre>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 1: Add a library called MathFunctions</span>
<span class="token comment"># Hint: You will need the add_library command</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>add_subdirectory</mark></p>
<p>为当前项目添加子目录。子目录当中必须包含一个CMakeLists.txt文件其中可以不写cmake_minimum_required与project。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>&lt;source_dir<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span></code></pre>
<p><mark>target_link_libraries</mark></p>
<p>为指定目录指定链接库。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span> ... &lt;item<span class="token punctuation">&gt;</span>... ...<span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> MathFunctions<span class="token punctuation">)</span></code></pre>
<p><mark>PROJECT_SOURCE_DIR</mark></p>
<p>最后一次调用project的CMakeLists.txt文件所在的目录。</p>
<p><mark>add_library</mark></p>
<p>用指定的源文件生成库文件。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>&lt;name<span class="token punctuation">&gt;</span> [&lt;source<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx MathFunctions.h<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="练习2-库文件可选编译">练习2 库文件可选编译</h3>
<p>本节内容为设置库文件(子目录)可选编译。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span>
<span class="token comment"># TODO 7: Create a variable USE_MYMATH using option and set default to ON</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use My Math?"</span> <span class="token boolean">OFF</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># TODO 8: Use list() and APPEND to create a list of optional libraries</span>
<span class="token comment"># called EXTRA_LIBS and a list of optional include directories called</span>
<span class="token comment"># EXTRA_INCLUDES. Add the MathFunctions library and source directory to</span>
<span class="token comment"># the appropriate lists.</span>
<span class="token comment">#</span>
<span class="token comment"># Only call add_subdirectory and only add MathFunctions specific values</span>
<span class="token comment"># to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true.</span>
<span class="token comment"># TODO 2: Use add_subdirectory() to add MathFunctions to this project</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_INCLUDES <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_SOURCE_DIR</span><span class="token punctuation">}</span></span>/MathFunctions"</span><span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values</span>
<span class="token comment"># in target_link_libraries.</span>
<span class="token comment"># TODO 3: Use target_link_libraries to link the library to our executable</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 4: Add MathFunctions to Tutorial's target_include_directories()</span>
<span class="token comment"># Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder!</span>
<span class="token comment"># TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values</span>
<span class="token comment"># in target_include_directories.</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">EXTRA_INCLUDES</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>option</mark></p>
<p>提供一个布尔变量,可以让用户自行选择。</p>
<p>用法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 用法</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> <span class="token string">"&lt;help_text&gt;"</span> [value]<span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use MyMath"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span></code></pre>
<p><code>value</code>值为<code>ON</code><code>OFF</code>,默认值为<code>OFF</code></p>
<p>在执行配置时,可以用<code>-D</code>来指定值,例如</p>
<pre><code class="fenced-code-block language-shell">cmake <span class="token builtin class-name">.</span> -DUSE_MYMATH<span class="token operator">=</span>OFF</code></pre>
<p><mark>if()</mark>&nbsp;&amp;&nbsp;<mark>endif()</mark></p>
<p>条件判断开始与结束。</p>
<p>语法:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span>&lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">elseif</span><span class="token punctuation">(</span>&lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<table>
<thead>
<tr>
<th align="center">&lt;condition&gt;判断为真的值</th>
<th align="center">&lt;condition&gt;判断为假的值</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="center">0</td>
</tr>
<tr>
<td align="center">ON</td>
<td align="center">OFF</td>
</tr>
<tr>
<td align="center">TRUE</td>
<td align="center">FALSE</td>
</tr>
<tr>
<td align="center">YES</td>
<td align="center">NO</td>
</tr>
<tr>
<td align="center">Y</td>
<td align="center">N</td>
</tr>
<tr>
<td align="center">其他非0数</td>
<td align="center">IGNORE</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">NOTFOUND或以-NOTFOUND结尾的</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">值不是判断为真的字符串</td>
</tr>
</tbody></table>
<p><mark>list</mark></p>
<p>列表操作。详细操作见<a href="#">list</a>这里只讲用到的APPEND操作。将一些元素追加到已有的列表当中。如果列表变量还未定义则会当做空列表处理。</p>
<p>语法与示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 语法</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND &lt;list<span class="token punctuation">&gt;</span> [&lt;element<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
<span class="token comment"># 示例 将MathFunctions追加到EXTRA_LIBS当中</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span></code></pre>
<p><mark>cmakedefine</mark></p>
<p>用法与#define相同用在configure_file的输入文件当中进行宏定义。</p>
<p>不同点在于,#define本身就是C/C++当中的宏定义所以不论对应的变量是否在CMakeLists.txt中有定义都会在输出文件中定义一个宏。而#cmakedfine则会根据变量在CMakeLists.txt中的定义情况来确定是否会在输出文件中定义宏。如果变量在CMakeLists.txt中没有定义或都已定义但是一个判断为假的布尔值则不会在输出文件中定义对应的宏如果变量在CMakeLists.txt中有定义且不为布尔值、或者为布尔值但判断为真则会在输出文件中定义对应的宏。</p>
<p>用法示例:</p>
<pre><code class="fenced-code-block language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">cmakedefine</span> <span class="token expression">USE_MYMATH</span></span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第三步-添加使用依赖">第三步 添加使用依赖</h2>
<h3 class="atx" id="练习1-为库添加使用依赖">练习1 为库添加使用依赖</h3>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD</span> <span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_CXX_STANDARD_REQUIRED</span> True<span class="token punctuation">)</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"OUT --- <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 删除EXTRA_INCLUDES</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 删除EXTRA_INCLUDES</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span></code></pre>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 1: 声明所有需要链接MathFunctions库的都要在头文件搜索中加入当前当前目录但是MathFunctions本身不需要</span>
<span class="token comment"># Hint: 用target_include_directories和INTERFACE </span>
<span class="token comment"># PUBLIC 本目标需要用,依赖这个目标的其他目标也需要用</span>
<span class="token comment"># INTERFACE 本目标不需要,依赖本目标的其他目标需要</span>
<span class="token comment"># PRIVATE 本目标需要,依赖这个目标的其他目标不需要</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions <span class="token namespace">INTERFACE</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"MathFunction --- <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>PUBLIC | INTERFACE | PRIVATE</mark></p>
<p>在使用<code>target_include_directories</code><code>target_link_libraries</code>添加搜索目录时,有三个修饰符<code>PUBLIC | INTERFACE | PRIVATE</code>,其含义如下:</p>
<p><strong>PUBLIC</strong>:当前目标和以当前目标为依赖的目标都能能使用添加的目录,都能在对应的目录中进行搜索</p>
<p><strong>PRIVATE</strong>:只有当前目标能使用添加的目录,以当前目标为依赖的目标不能使用</p>
<p><strong>INTERFACE</strong>以当前目标为依赖的目标需要使用添加的目录但当前目标不需要用这种方式添加对应搜索目录时用INTERFACE。</p>
<p>&nbsp;</p>
<p><mark>CMAKE_CURRENT_SOURCE_DIR</mark></p>
<p>变量。当前CMakeLists.txt所在的目录。</p>
<p>&nbsp;</p>
<p><strong>课后练习</strong></p>
<p>①找一个外部的头文件目录分别在两个cxx文件里引用并用本节内容方法在MathFunctions/CMakeLists.txt里添加使用依赖分别使用PUBLIC | INTERFACE | PRIVATE修饰符查看编译报错信息验证本节所讲知识点。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第四步-生成器表达式">第四步 生成器表达式</h2>
<h3 class="atx" id="练习1-用接口库设置c标准">练习1 用接口库设置C++标准</h3>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 4: Update the minimum required version to 3.15</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 1: 将下面的代码替换为:</span>
<span class="token comment"># * 创建一个interface库tutorial_compiler_flags</span>
<span class="token comment"># Hint: use add_library() with the INTERFACE signature</span>
<span class="token comment"># * 添加编译特性cxx_std_11到tutorial_compiler_flags</span>
<span class="token comment"># Hint: Use target_compile_features()</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_14</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 5: 创建一些辅助变量用来确定用的是哪个编译器:</span>
<span class="token comment"># * 创建一个变量gcc_like_cxx如果用的是CXX并且用的是下列任意一个编译器那么值为true</span>
<span class="token comment"># ARMClang, AppleClang, Clang, GNU, LCC</span>
<span class="token comment"># * 创建一个变量msvc_cxx如果用的是CXX和MSVC那么值为true</span>
<span class="token comment"># Hint: Use set() and COMPILE_LANG_AND_ID</span>
<span class="token comment"># TODO 6: 向interface库tutorial_compiler_flags中添加警告选项</span>
<span class="token comment"># </span>
<span class="token comment"># * 如果是gcc_like_cxx, 添加 -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused</span>
<span class="token comment"># * 如果是msvc_cxx, 添加 -W3</span>
<span class="token comment"># Hint: Use target_compile_options()</span>
<span class="token comment"># TODO 7: 用嵌套生成器表达式, 只在构建的时警告</span>
<span class="token comment"># </span>
<span class="token comment"># Hint: Use BUILD_INTERFACE</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 链接tutorial_compiler_flags</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span> tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span></code></pre>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx<span class="token punctuation">)</span>
<span class="token comment"># state that anybody linking to us needs to include the current source dir</span>
<span class="token comment"># to find MathFunctions.h, while we don't.</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">INTERFACE</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 链接tutorial_compiler_flags</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>MathFunctions <span class="token namespace">PUBLIC</span> tutorial_compiler_flags<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>INTERFACE库</mark></p>
<p>使用<code>add_library(&lt;libname&gt; INTERFACE)</code>可以创建个Interface库这样的库并不是真实存在的是一个虚拟的库通常用来传递一些选项。用法和正常的库一样可通过<code>target_link_libraries</code>链接到目标,可以向指定的目标传递一些指定的参数选项。</p>
<p>&nbsp;</p>
<p><mark>target_compile_features</mark></p>
<p><code>target_compile_features</code> 是 CMake 用来指定编译器特性的命令。它可以用来指定编译器需要支持的 C++ 标准或者其他编译器特性。具体支持的特性取决于编译器版本和 CMake 版本。</p>
<p>语法与示例</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span> &lt;<span class="token namespace">PRIVATE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">INTERFACE</span><span class="token punctuation">&gt;</span> &lt;feature<span class="token punctuation">&gt;</span> [...]<span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_11</span><span class="token punctuation">)</span></code></pre>
<p>以下是一些常见的特性:</p>
<ul>
<li><code>cxx_std_11</code>:指定 C++11 标准。</li>
<li><code>cxx_std_14</code>:指定 C++14 标准。</li>
<li><code>cxx_std_17</code>:指定 C++17 标准。</li>
<li><code>cxx_std_20</code>:指定 C++20 标准。</li>
<li><code>cxx_constexpr</code>:启用 C++11 constexpr 函数。</li>
<li><code>cxx_nullptr</code>:启用 C++11 nullptr 关键字。</li>
<li><code>cxx_auto_type</code>:启用 C++11 auto 关键字。</li>
<li><code>cxx_lambdas</code>:启用 C++11 lambda 表达式。</li>
<li><code>cxx_range_for</code>:启用 C++11 range-based for 循环。</li>
<li><code>cxx_override</code>:启用 C++11 override 关键字。</li>
<li><code>cxx_final</code>:启用 C++11 final 关键字。</li>
</ul>
<p>&nbsp;</p>
<h3 class="atx" id="练习2-添加编译警告选项">练习2 添加编译警告选项</h3>
<p><strong>CMakeLists.txt解析过程</strong></p>
<p>CMake构建过程分为两个阶段</p>
<ol>
<li>配置阶段CMake 会读取项目的 CMakeLists.txt 文件,并根据其中的指令和参数来生成 Makefile 或者 IDE 的项目文件<ul>
<li>检查编译器和工具链是否可用,并设置编译器选项和链接选项</li>
<li>检查系统库和第三方库是否可用,并设置库的路径和链接选项</li>
<li>检查项目的源代码文件,并设置编译选项和链接选项</li>
<li>生成 Makefile 或者 IDE 的项目文件</li>
<li>根据不同的平台和编译器生成不同的 Makefile 或者项目文件,以保证项目可以在不同的平台和编译器上构建</li>
</ul>
</li>
<li>生成阶段CMake 会根据配置阶段生成的 Makefile 或者项目文件来执行实际的构建操作<ul>
<li>根据 Makefile 或者项目文件中的指令和参数来编译源代码文件,并生成目标文件</li>
<li>根据 Makefile 或者项目文件中的指令和参数来链接目标文件,并生成可执行文件或者库文件</li>
</ul>
</li>
</ol>
<p>&nbsp;</p>
<p><strong>生成器表达式</strong></p>
<p>CMake生成器表达式是一种特殊的语法用于在CMake构建系统中动态地生成构建规则。它们可以用于指定编译器选项、链接选项等。</p>
<p>本节先学习其中两种表达式:</p>
<p><strong>$&lt;condition:true_string&gt;</strong></p>
<ul>
<li>如果<code>condition</code>为1则此表达式结果为<code>true_string</code></li>
<li>如果<code>condition</code>为0则此表达式结果为空</li>
</ul>
<p><strong>$&lt;COMPILE_LANG_AND_ID:language,compiler_ids&gt;</strong></p>
<ul>
<li>如果当前所用的语言与<code>language</code>一致且编译器ID在<code>compiler_ids</code>的列表中则表达式值为1否则为0</li>
<li><code>language</code>值主要为<code>CXX</code><code>C</code></li>
<li><code>compiler_ids</code>主要有GNU、Clang、MSVC等有多个时用逗号隔开</li>
</ul>
<p>生成器表达式因为是在生成阶段可用,所以不能在配置阶段进行输出 ,可用下面方式调式</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_custom_target</span><span class="token punctuation">(</span>ged COMMAND <span class="token punctuation">${</span><span class="token variable">CMAKE_COMMAND</span><span class="token punctuation">}</span> -E echo <span class="token string">"$&lt;1:hello&gt;"</span><span class="token punctuation">)</span></code></pre>
<p>配置完成之后,用以下命令进行输出</p>
<pre><code class="fenced-code-block language-shell">cmake --build <span class="token builtin class-name">.</span> --target ged
<span class="token comment"># 用make可简写</span>
<span class="token function">make</span> ged</code></pre>
<p>但不是所有的表达式都能这样输出,有的表达式无法输出,比如<code>$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC&gt;</code></p>
<p>&nbsp;</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># TODO 4: Update the minimum required version to 3.15</span>
<span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.15</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 1: 将下面的代码替换为:</span>
<span class="token comment"># * 创建一个interface库tutorial_compiler_flags</span>
<span class="token comment"># Hint: use add_library() with the INTERFACE signature</span>
<span class="token comment"># * 添加编译特性cxx_std_11到tutorial_compiler_flags</span>
<span class="token comment"># Hint: Use target_compile_features()</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_14</span><span class="token punctuation">)</span>
<span class="token comment"># add_custom_target(ged COMMAND ${CMAKE_COMMAND} -E echo "$&lt;COMPILE_LANG_AND_ID:CXX,GNU&gt;")</span>
<span class="token comment"># TODO 5: 创建一些辅助变量用来确定用的是哪个编译器:</span>
<span class="token comment"># * 创建一个变量gcc_like_cxx如果用的是CXX并且用的是下列任意一个编译器那么值为true</span>
<span class="token comment"># ARMClang, AppleClang, Clang, GNU, LCC</span>
<span class="token comment"># * 创建一个变量msvc_cxx如果用的是CXX和MSVC那么值为true</span>
<span class="token comment"># Hint: Use set() and COMPILE_LANG_AND_ID</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>gcc_like_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>msvc_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 6: 向interface库tutorial_compiler_flags中添加警告选项</span>
<span class="token comment"># </span>
<span class="token comment"># * 如果是gcc_like_cxx, 添加 -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused</span>
<span class="token comment"># * 如果是msvc_cxx, 添加 -W3</span>
<span class="token comment"># Hint: Use target_compile_options()</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">gcc_like_cxx</span><span class="token punctuation">}</span></span>:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;"</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">msvc_cxx</span><span class="token punctuation">}</span></span>:-W3&gt;"</span>
<span class="token punctuation">)</span>
<span class="token comment"># TODO 7: 用嵌套生成器表达式, 只在构建的时警告</span>
<span class="token comment"># </span>
<span class="token comment"># Hint: Use BUILD_INTERFACE</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># TODO 2: 链接tutorial_compiler_flags</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span> tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>target_compile_options</mark></p>
<p>给指定的目标添加编译选项。</p>
<p>语法及示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span> [BEFORE]
&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items1...]
[&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items2...] ...]<span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> -std=c++<span class="token number">11</span> -Wunused<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p><strong>课后练习</strong></p>
<p>①有余力的同学自行探究一下生成器表达式的其他内容。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第五步-安装与测试">第五步 安装与测试</h2>
<h3 class="atx" id="练习1-安装规则">练习1 安装规则</h3>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.15</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_11</span><span class="token punctuation">)</span>
<span class="token comment"># add compiler warning flags just when building this project via</span>
<span class="token comment"># the BUILD_INTERFACE genex</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>gcc_like_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>msvc_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">gcc_like_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">msvc_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span>
<span class="token punctuation">)</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span> tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 安装 Tutorial 到 bin 目录 ${CMAKE_INSTALL_PREFIX}</span>
<span class="token comment"># Hint: Use the TARGETS and DESTINATION parameters</span>
<span class="token comment"># install(TARGETS targets... [DESTINATION &lt;dir&gt;])</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS Tutorial DESTINATION bin<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_INSTALL_PREFIX</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 4: 安装TutorialConfig.h到include目录</span>
<span class="token comment"># Hint: Use the FILES and DESTINATION parameters</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>/TutorialConfig.h"</span> DESTINATION include<span class="token punctuation">)</span></code></pre>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx<span class="token punctuation">)</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">INTERFACE</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>installable_libs MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>TARGET SqrtLibrary<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND installable_libs SqrtLibrary<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS <span class="token punctuation">${</span>installable_libs<span class="token punctuation">}</span> DESTINATION lib<span class="token punctuation">)</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES MathFunctions.h DESTINATION include<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>if(TARGET target-name)</mark></p>
<ul>
<li>如果<code>target-name</code>是一个已经调用<code>add_executable</code><code>add_library</code><code>add_custom_target</code>创建的目标则返回True</li>
</ul>
<pre><code class="fenced-code-block language-cmake"></code></pre>
<p><mark>install</mark></p>
<p>用于定义安装规则。</p>
<p>语法与示例(简洁版)</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 安装生成的目标文件</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS &lt;目标名列表<span class="token punctuation">&gt;</span> DESTINATION &lt;安装位置<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 安装其他文件</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES &lt;文件列表<span class="token punctuation">&gt;</span> DESTINATION &lt;安装位置<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p>安装多个文件时,用空格隔开。安装位置是相对于<code>CMAKE_INSTALL_PREFIX</code>的,<code>CMAKE_INSTALL_PREFIX</code>是安装时的默认路径,可以自行用<code>set</code>设置。</p>
<p>运行安装:</p>
<p>安装到默认路径下</p>
<pre><code class="fenced-code-block language-shell">cmake --install <span class="token builtin class-name">.</span></code></pre>
<p>如果有多个生成版本,指定安装版本</p>
<pre><code class="fenced-code-block language-shell">cmake --install <span class="token builtin class-name">.</span> --config Release</code></pre>
<p>如果用的是IDE用下列命令</p>
<pre><code class="fenced-code-block language-shell">cmake --build <span class="token builtin class-name">.</span> --target <span class="token function">install</span> --config Debug</code></pre>
<p>自行指定安装路径</p>
<pre><code class="fenced-code-block language-shell">cmake --install <span class="token builtin class-name">.</span> --prefix <span class="token string">"/path/to/your/installdir"</span></code></pre>
<p>&nbsp;</p>
<h3 class="atx" id="练习2-测试支持">练习2 测试支持</h3>
<p><code>CTest</code>提供了一些测试管理。本节内容为给可执行文件创建单元测试。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.15</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_11</span><span class="token punctuation">)</span>
<span class="token comment"># add compiler warning flags just when building this project via</span>
<span class="token comment"># the BUILD_INTERFACE genex</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>gcc_like_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>msvc_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">gcc_like_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">msvc_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span>
<span class="token punctuation">)</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span> tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 安装 Tutorial 到 bin 目录 ${CMAKE_INSTALL_PREFIX}</span>
<span class="token comment"># Hint: Use the TARGETS and DESTINATION parameters</span>
<span class="token comment"># install(TARGETS targets... [DESTINATION &lt;dir&gt;])</span>
<span class="token comment"># target: add_excutable add_library</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS Tutorial DESTINATION bin<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_INSTALL_PREFIX</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 4: 安装TutorialConfig.h到include目录</span>
<span class="token comment"># Hint: Use the FILES and DESTINATION parameters</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>/TutorialConfig.h"</span> DESTINATION include<span class="token punctuation">)</span>
<span class="token comment"># TODO 5: Enable testing</span>
<span class="token keyword">enable_testing</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 6: 添加一个Runs测试运行下面的命令:</span>
<span class="token comment"># $ Tutorial 25</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Runs COMMAND Tutorial <span class="token number">25</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 7: 添加一个叫Usage的测试执行下面的命令:</span>
<span class="token comment"># $ Tutorial</span>
<span class="token comment"># 要保证输出期望的内容.</span>
<span class="token comment"># Hint: 用PASS_REGULAR_EXPRESSION属性匹配"Usage.*number"</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Usage COMMAND Tutorial<span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Usage <span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token string">"Usage.*number"</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 8: 再添加一个运行下面命令的测试:</span>
<span class="token comment"># $ Tutorial 4</span>
<span class="token comment"># 保证输出结果是正确的.</span>
<span class="token comment"># Hint: 用PASS_REGULAR_EXPRESSION属性匹配"4 is 2"</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Com4 COMMAND Tutorial <span class="token number">4</span><span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Com4 <span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token string">"4 is 2"</span><span class="token punctuation">)</span>
<span class="token comment"># TODO 9: 添加更多测试. 创建一个函数do_test完成重复内容</span>
<span class="token comment"># 测试以下数值: 4, 9, 5, 7, 25, -25 and 0.0001.</span>
<span class="token keyword">function</span><span class="token punctuation">(</span>do_test num result<span class="token punctuation">)</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Com<span class="token punctuation">${</span>num<span class="token punctuation">}</span> COMMAND Tutorial <span class="token punctuation">${</span>num<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Com<span class="token punctuation">${</span>num<span class="token punctuation">}</span> <span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">num</span><span class="token punctuation">}</span></span> is <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span><span class="token number">9</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span><span class="token number">5</span> <span class="token number">2.236</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span><span class="token number">7</span> <span class="token number">2.645</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>-<span class="token number">25</span> <span class="token string">"(-nan|nan|0)"</span><span class="token punctuation">)</span> <span class="token comment"># not a number</span>
<span class="token function">do_test</span><span class="token punctuation">(</span><span class="token number">0.0001</span> <span class="token number">0.001</span><span class="token punctuation">)</span>
<span class="token comment"># 5 2.236</span>
<span class="token comment"># 7 2.645</span>
<span class="token comment"># -25 "(-nan|nan|0)"</span>
<span class="token comment"># 0.0001 0.001</span>
<span class="token comment"># do_test(4 2)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>enable_testing()</mark></p>
<p>开启当前目录及子目录的测试支持。</p>
<p><mark>add_test</mark></p>
<p>添加一条测试</p>
<p>简版用法:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> &lt;name<span class="token punctuation">&gt;</span> COMMAND &lt;command<span class="token punctuation">&gt;</span> [&lt;arg<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>name</code>为本条测试名称</li>
<li><code>command</code>测试用的命令</li>
<li><code>arg</code>传递测试命令的参数</li>
</ul>
<p><mark>set_tests_properties</mark></p>
<p>设置测试的属性。</p>
<p>语法</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>test1 [test2...] <span class="token namespace">PROPERTIES</span> prop1 value1 prop2 value2<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>test1...</code>为用add_test添加的测试名</li>
<li><code>prop1</code>为需要设置的属性名,本节中只学<code>PASS_REGULAR_EXPRESSION</code>,表示测试程序的输出结果需要能匹配<code>value</code>所表示的正则表达式才能通过,如果匹配不了则不通过。</li>
<li><code>value</code>要设置的属性值</li>
</ul>
<p>示例</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Usage
<span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token string">"Usage:.*number"</span>
<span class="token punctuation">)</span></code></pre>
<p>表示运行<code>Usage</code>这个测试时测试程序的输出结果要能正则匹配到"Usage:.*number"。</p>
<p><mark>function()与endfunction()</mark></p>
<p>用于在定义函数,分别表示函数开始与函数结束</p>
<p>语法</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>&lt;name<span class="token punctuation">&gt;</span> [&lt;arg1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<ul>
<li>括号里第一个参数为函数名,后面是参数列表,可以有多个,多个参数用空格隔开</li>
</ul>
<p>示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 定义</span>
<span class="token keyword">function</span><span class="token punctuation">(</span>do_test target arg result<span class="token punctuation">)</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Comp<span class="token punctuation">${</span>arg<span class="token punctuation">}</span> COMMAND <span class="token punctuation">${</span>target<span class="token punctuation">}</span> <span class="token punctuation">${</span>arg<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Comp<span class="token punctuation">${</span>arg<span class="token punctuation">}</span>
<span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token punctuation">${</span>result<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 调用</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">4</span> <span class="token string">"4 is 1"</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第六步-添加测试面板支持">第六步 添加测试面板支持</h2>
<h3 class="atx" id="练习1-发送测试结果到测试面板">练习1 发送测试结果到测试面板</h3>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 将enable_testing()替换为下面这行</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CTest<span class="token punctuation">)</span></code></pre>
<p>在build目录执行</p>
<pre><code class="fenced-code-block language-shell">cmake -G <span class="token string">"MinGW Makefiles"</span> <span class="token punctuation">..</span></code></pre>
<p>之后执行</p>
<pre><code class="fenced-code-block language-shell">ctest -VV -D Experimental</code></pre>
<p>即可。</p>
<p>完成之后可在<a href="https://my.cdash.org/index.php?project=CMakeTutorial%E6%9F%A5%E7%9C%8B%E6%8F%90%E4%BA%A4%E7%9A%84%E6%B5%8B%E8%AF%95%E7%BB%93%E6%9E%9C%E3%80%82">https://my.cdash.org/index.php?project=CMakeTutorial查看提交的测试结果。</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第七步-添加系统特性检查">第七步 添加系统特性检查</h2>
<h3 class="atx" id="练习1-评估依赖可用性">练习1 评估依赖可用性</h3>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx<span class="token punctuation">)</span>
<span class="token comment"># state that anybody linking to us needs to include the current source dir</span>
<span class="token comment"># to find MathFunctions.h, while we don't.</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">INTERFACE</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token comment"># link our compiler flags interface library</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># TODO 1: Include CheckCXXSourceCompiles</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CheckCXXSourceCompiles<span class="token punctuation">)</span>
<span class="token comment"># TODO 2:用check_cxx_source_compiles和简单C++代码检测</span>
<span class="token comment"># 以下两个函数是否可用:</span>
<span class="token comment"># * std::log ln</span>
<span class="token comment"># * std::exp e^2</span>
<span class="token comment"># 把结果存在HAVE_LOG 和 HAVE_EXP 中.</span>
<span class="token comment"># Hint: Sample C++ code which uses log:</span>
<span class="token comment"># #include &lt;cmath&gt;</span>
<span class="token comment"># int main() {</span>
<span class="token comment"># std::log(1.0);</span>
<span class="token comment"># return 0;</span>
<span class="token comment"># }</span>
<span class="token function">check_cxx_source_compiles</span><span class="token punctuation">(</span><span class="token string">"
#include &lt;cmath&gt;
int main() {
std::log(1.0);
return 0;
}
"</span> HAVE_LOG<span class="token punctuation">)</span>
<span class="token function">check_cxx_source_compiles</span><span class="token punctuation">(</span><span class="token string">"
#include &lt;cmath&gt;
int main() {
std::exp(1.0);
return 0;
}
"</span> HAVE_EXP<span class="token punctuation">)</span>
<span class="token comment"># TODO 3: 如果HAVE_LOG和HAVE_EXP为真, 添加预编译定义</span>
<span class="token comment"># "HAVE_LOG"和"HAVE_EXP"到目标MathFunctions上.</span>
<span class="token comment">#Hint: Use target_compile_definitions()</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>HAVE_LOG <span class="token operator">AND</span> HAVE_EXP<span class="token punctuation">)</span>
<span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>MathFunctions <span class="token namespace">PRIVATE</span> <span class="token string">"HAVE_LOG"</span> <span class="token string">"HAVE_EXP"</span><span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># install libs</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>installable_libs MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS <span class="token punctuation">${</span>installable_libs<span class="token punctuation">}</span> DESTINATION lib<span class="token punctuation">)</span>
<span class="token comment"># install include headers</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES MathFunctions.h DESTINATION include<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>include</mark></p>
<p>用于导入其他CMake文件或模块。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">include</span><span class="token punctuation">(</span>&lt;file|module<span class="token punctuation">&gt;</span> [OPTIONAL] [RESULT_VARIABLE &lt;var<span class="token punctuation">&gt;</span>]
[NO_POLICY_SCOPE]<span class="token punctuation">)</span></code></pre>
<p><mark>check_cxx_source_compiles</mark></p>
<p>检查给定的C++代码能不能编译及链接成可执行文件。通常用来检查当前环境中是否具有某些特性。</p>
<p>用法</p>
<pre><code class="fenced-code-block language-cmake"><span class="token function">check_cxx_source_compiles</span><span class="token punctuation">(</span>&lt;code<span class="token punctuation">&gt;</span> &lt;resultVar<span class="token punctuation">&gt;</span> [FAIL_REGEX &lt;regex1<span class="token punctuation">&gt;</span> [&lt;regex2<span class="token punctuation">&gt;</span>...]]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>code</code>为需要检查的代码,需要包含<code>main</code>函数</li>
<li><code>resultVar</code>为检查结果,如果成功返回布尔真,否则返回布尔假</li>
<li><code>FAIL_REGEX</code>如果提供,则返回为假的结果需要能匹配上对应的正则表达式</li>
</ul>
<p><mark>target_compile_definitions</mark></p>
<p>为指定可执行文件及库文件这类目标添加编译器定义,用来控制代码中的条件编译。有点类似于<code>#cmakedefine</code><code>configure_file</code>的作用,但这两个操作的结果会生成一个文件再进行引用,而<code>target_compile_definitions</code>不会生成文件。</p>
<p>用法</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span>
&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items1...]
[&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items2...] ...]<span class="token punctuation">)</span></code></pre>
<p>示例</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>MathFunctions <span class="token namespace">PRIVATE</span> <span class="token string">"HAVE_LOG"</span> <span class="token string">"HAVE_EXP"</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第八步-添加自定义命令及用自定义命令生成文件">第八步 添加自定义命令及用自定义命令生成文件</h2>
<p>在Linux中有许多的工具命令例如<code>ls</code><code>mv</code><code>mkdir</code>等。在CMake项目中可以用源代码写一些自定义小工具然后在CMake中进行调用来完成一些工作。</p>
<p>本节的内容为自定义一个<code>MakeTable</code>命令用来生成指定范围整数的平方根并保存到文件中,在计算的时候可以用这些已经计算好的值来辅助计算。</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_library</span><span class="token punctuation">(</span>MathFunctions mysqrt.cxx Table.h<span class="token punctuation">)</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>MakeTable MakeTable.cxx<span class="token punctuation">)</span>
<span class="token keyword">add_custom_command</span><span class="token punctuation">(</span>
OUTPUT <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span>/Table.h
COMMAND MakeTable <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span>/Table.h
<span class="token property">DEPENDS</span> MakeTable
<span class="token punctuation">)</span>
<span class="token comment"># state that anybody linking to us needs to include the current source dir</span>
<span class="token comment"># to find MathFunctions.h, while we don't.</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">INTERFACE</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span>
<span class="token namespace">PRIVATE</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token comment"># link our compiler flags interface library</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># does this system provide the log and exp functions?</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CheckCXXSourceCompiles<span class="token punctuation">)</span>
<span class="token function">check_cxx_source_compiles</span><span class="token punctuation">(</span><span class="token string">"
#include &lt;cmath&gt;
int main() {
std::log(1.0);
return 0;
}
"</span> HAVE_LOG<span class="token punctuation">)</span>
<span class="token function">check_cxx_source_compiles</span><span class="token punctuation">(</span><span class="token string">"
#include &lt;cmath&gt;
int main() {
std::exp(1.0);
return 0;
}
"</span> HAVE_EXP<span class="token punctuation">)</span>
<span class="token comment"># add compile definitions</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>HAVE_LOG <span class="token operator">AND</span> HAVE_EXP<span class="token punctuation">)</span>
<span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">PRIVATE</span> <span class="token string">"HAVE_LOG"</span> <span class="token string">"HAVE_EXP"</span><span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># install libs</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>installable_libs MathFunctions tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS <span class="token punctuation">${</span>installable_libs<span class="token punctuation">}</span> DESTINATION lib<span class="token punctuation">)</span>
<span class="token comment"># install include headers</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES MathFunctions.h DESTINATION include<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>add_custom_command</mark></p>
<p>执行自定义指令。</p>
<p>简版用法</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_custom_command</span><span class="token punctuation">(</span>OUTPUT output1
COMMAND command1
<span class="token property">DEPENDS</span> depends<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>OUTPUT</code>指定输出文件名</li>
<li><code>COMMAND</code>指定要执行的指令</li>
<li><code>DEPENDS</code>执行指令需要依赖的内容。如果是由<code>add_executable</code><code>add_library</code>添加的目标名,写这一条可以保证对应目标的生成。</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第九步-打包安装程序">第九步 打包安装程序</h2>
<p>发布程序可以有多种形式比如安装包、压缩包、源文件等。CMake也提供了打包程序<code>cpack</code>可将程序打包成多种形式。</p>
<p>只需要在顶层CMakelists.txt中添加以下代码</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">include</span><span class="token punctuation">(</span>InstallRequiredSystemLibraries<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>CPACK_RESOURCE_FILE_LICENSE <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span></span>/License.txt"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CPACK_PACKAGE_VERSION_MAJOR</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MAJOR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CPACK_PACKAGE_VERSION_MINOR</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MINOR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>CPACK_SOURCE_GENERATOR <span class="token string">"TGZ"</span><span class="token punctuation">)</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CPack<span class="token punctuation">)</span></code></pre>
<p>在项目构建完成之后,可以直接执行</p>
<pre><code class="fenced-code-block language-shell">cpack</code></pre>
<p>在Windows上默认情况会打包成.exe文件所以需要先安装一个exe打包程序NSIS(Null Soft Installer)</p>
<p>NSIS下载地址<a href="https://sourceforge.net/projects/nsis/">https://sourceforge.net/projects/nsis/</a></p>
<p>也可以指定生成器打包成对应的格式</p>
<pre><code class="fenced-code-block language-shell">cpack -G ZIP <span class="token comment"># 打包成ZIP</span></code></pre>
<p>具体生成器各类可以通过<code>cpack --help</code>查看</p>
<p>对于多配置项目,可以指定打包配置</p>
<pre><code class="fenced-code-block language-shell">cpack -C Debug <span class="token comment"># 打包Debug版本</span></code></pre>
<p>也可以打包源代码</p>
<pre><code class="fenced-code-block language-shell">cpack --config CPackSourceConfig.cmake</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第十步-选择静态链接库或动态链接库">第十步 选择静态链接库或动态链接库</h2>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.15</span><span class="token punctuation">)</span>
<span class="token comment"># set the project name and version</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial <span class="token property">VERSION</span> <span class="token number">1.0</span><span class="token punctuation">)</span>
<span class="token comment"># specify the C++ standard</span>
<span class="token keyword">add_library</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_features</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span> <span class="token property">cxx_std_11</span><span class="token punctuation">)</span>
<span class="token comment"># add compiler warning flags just when building this project via</span>
<span class="token comment"># the BUILD_INTERFACE genex</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>gcc_like_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>msvc_cxx <span class="token string">"$&lt;COMPILE_LANG_AND_ID:CXX,MSVC&gt;"</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">gcc_like_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">msvc_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span>
<span class="token punctuation">)</span>
<span class="token comment"># should we use our own math functions</span>
<span class="token keyword">option</span><span class="token punctuation">(</span>USE_MYMATH <span class="token string">"Use tutorial provided math implementation"</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token keyword">option</span><span class="token punctuation">(</span><span class="token variable">BUILD_SHARED_LIBS</span> <span class="token string">"Use Dynamic? "</span> <span class="token boolean">ON</span><span class="token punctuation">)</span>
<span class="token comment"># configure a header file to pass some of the CMake settings</span>
<span class="token comment"># to the source code</span>
<span class="token keyword">configure_file</span><span class="token punctuation">(</span>TutorialConfig.h.in TutorialConfig.h<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_ARCHIVE_OUTPUT_DIRECTORY</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span> <span class="token comment"># .a .lib</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_RUNTIME_OUTPUT_DIRECTORY</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span> <span class="token comment"># .dll .exe</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_LIBRARY_OUTPUT_DIRECTORY</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span> <span class="token comment"># .so</span>
<span class="token comment"># add the MathFunctions library</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>USE_MYMATH<span class="token punctuation">)</span>
<span class="token keyword">add_subdirectory</span><span class="token punctuation">(</span>MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND EXTRA_LIBS MathFunctions<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># add the executable</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> <span class="token punctuation">${</span>EXTRA_LIBS<span class="token punctuation">}</span> tutorial_compiler_flags<span class="token punctuation">)</span>
<span class="token comment"># add the binary tree to the search path for include files</span>
<span class="token comment"># so that we will find TutorialConfig.h</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>"</span>
<span class="token punctuation">)</span>
<span class="token comment"># add the install targets</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS Tutorial DESTINATION bin<span class="token punctuation">)</span>
<span class="token keyword">install</span><span class="token punctuation">(</span>FILES <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">PROJECT_BINARY_DIR</span><span class="token punctuation">}</span></span>/TutorialConfig.h"</span>
DESTINATION include
<span class="token punctuation">)</span>
<span class="token comment"># enable testing</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CTest<span class="token punctuation">)</span>
<span class="token comment"># does the application run</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Runs COMMAND Tutorial <span class="token number">25</span><span class="token punctuation">)</span>
<span class="token comment"># does the usage message work?</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Usage COMMAND Tutorial<span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Usage
<span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token string">"Usage:.*number"</span>
<span class="token punctuation">)</span>
<span class="token comment"># define a function to simplify adding tests</span>
<span class="token keyword">function</span><span class="token punctuation">(</span>do_test target arg result<span class="token punctuation">)</span>
<span class="token keyword">add_test</span><span class="token punctuation">(</span><span class="token property">NAME</span> Comp<span class="token punctuation">${</span>arg<span class="token punctuation">}</span> COMMAND <span class="token punctuation">${</span>target<span class="token punctuation">}</span> <span class="token punctuation">${</span>arg<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>Comp<span class="token punctuation">${</span>arg<span class="token punctuation">}</span>
<span class="token namespace">PROPERTIES</span> <span class="token property">PASS_REGULAR_EXPRESSION</span> <span class="token punctuation">${</span>result<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># do a bunch of result based tests</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">4</span> <span class="token string">"4 is 2"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">9</span> <span class="token string">"9 is 3"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">5</span> <span class="token string">"5 is 2.236"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">7</span> <span class="token string">"7 is 2.645"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">25</span> <span class="token string">"25 is 5"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial -<span class="token number">25</span> <span class="token string">"-25 is (-nan|nan|0)"</span><span class="token punctuation">)</span>
<span class="token function">do_test</span><span class="token punctuation">(</span>Tutorial <span class="token number">0.0001</span> <span class="token string">"0.0001 is 0.01"</span><span class="token punctuation">)</span>
<span class="token comment"># setup installer</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>InstallRequiredSystemLibraries<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>CPACK_RESOURCE_FILE_LICENSE <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span></span>/License.txt"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CPACK_PACKAGE_VERSION_MAJOR</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MAJOR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CPACK_PACKAGE_VERSION_MINOR</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MINOR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>CPACK_SOURCE_GENERATOR <span class="token string">"TGZ"</span><span class="token punctuation">)</span>
<span class="token keyword">include</span><span class="token punctuation">(</span>CPack<span class="token punctuation">)</span></code></pre>
<p><strong>要点</strong></p>
<p><mark>BUILD_SHARED_LIBS</mark></p>
<p>全局为<code>add_library</code>设置库的生成类型。<code>ON</code>则生成动态链接库,<code>OFF</code>则生成静态链接库。</p>
<p><mark>CMAKE_ARCHIVE_OUTPUT_DIRECTORY</mark></p>
<p>指定静态库文件的生成位置。</p>
<p><mark>CMAKE_RUNTIME_OUTPUT_DIRECTORY</mark></p>
<p>指定执行文件的生成位置包括可执行程序和Windows上动态库文件(.dll)</p>
<p><mark>CMAKE_LIBRARY_OUTPUT_DIRECTORY</mark></p>
<p>非Windows平台上的生成的.so库文件</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第十一步-添加导出配置">第十一步 添加导出配置</h2>
<p>先来复习一下在CMake中使用其他库的方法。本节把<code>MathFunctions</code>生成的库文件、头文件放到其他路径当中,这时库的引入方式如下:</p>
<p><code>CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial<span class="token punctuation">)</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>mathlib_DIR C:/Users/YAN/Desktop/cmake/mathlib<span class="token punctuation">)</span>
<span class="token comment"># cmake中使用第三方库的一般步骤</span>
<span class="token comment"># 1. 设置头文件位置</span>
<span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PRIVATE</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">mathlib_DIR</span><span class="token punctuation">}</span></span>/include"</span><span class="token punctuation">)</span>
<span class="token comment"># 2. 设置库文件搜索位置</span>
<span class="token keyword">target_link_directories</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PRIVATE</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">mathlib_DIR</span><span class="token punctuation">}</span></span>/lib"</span><span class="token punctuation">)</span>
<span class="token comment"># 3. 指定需要链接的库libXXX.a libXXX.dll直接写成XXX的形式即可</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PRIVATE</span> MathFunctions<span class="token punctuation">)</span></code></pre>
<p>现在的问题是如果一个库不用CMake管理那就是用如上方法来引用可是这个库也是由CMake构建来的还用同样的方法来引入那CMake不是白用了吗</p>
<p>用CMake管理简化后的版本为</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_minimum_required</span><span class="token punctuation">(</span><span class="token property">VERSION</span> <span class="token number">3.10</span><span class="token punctuation">)</span>
<span class="token keyword">project</span><span class="token punctuation">(</span>Tutorial<span class="token punctuation">)</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token comment"># 如果库是安装在环境变量里有的位置,这行可以不用写</span>
<span class="token comment"># set(MathFunctions_DIR C:/Users/YAN/Desktop/cmake/mathlib/lib/cmake/MathFunctions)</span>
<span class="token keyword">find_package</span><span class="token punctuation">(</span>MathFunctions REQUIRED<span class="token punctuation">)</span>
<span class="token keyword">target_link_libraries</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PRIVATE</span> MathFunctions<span class="token punctuation">)</span></code></pre>
<p>所以本节内容为如何导出一个用CMake管理的库。</p>
<p><strong>第一步</strong> 将目标安装添加导出</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">install</span><span class="token punctuation">(</span>TARGETS <span class="token punctuation">${</span>installable_libs<span class="token punctuation">}</span>
EXPORT MathFunctionsTargets
DESTINATION lib<span class="token punctuation">)</span></code></pre>
<p><code>EXPORT</code>可以生成一个<code>MathFunctionsTargets.cmake</code>的文件,里面描述了此处安装的这些目标的一些导出配置。</p>
<p><strong>第二步</strong> 要让导出文件配置的路径对其他项目也可用,而不是绑定当前项目路径,需要修改头文件搜索路径,构建时和安装后为不同值</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_include_directories</span><span class="token punctuation">(</span>MathFunctions
<span class="token namespace">INTERFACE</span>
<span class="token punctuation">$&lt;</span>BUILD_INTERFACE:<span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span><span class="token punctuation">&gt;</span>
<span class="token punctuation">$&lt;</span>INSTALL_INTERFACE:include<span class="token punctuation">&gt;</span>
<span class="token punctuation">)</span></code></pre>
<p><strong>第三步</strong> 安装生成的<code>MathFunctionsTargets.cmake</code></p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">install</span><span class="token punctuation">(</span>EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
<span class="token punctuation">)</span></code></pre>
<p><strong>第四步</strong> 准备<code>MathFunctionsConfig.cmake</code>文件模板与生成</p>
<p>用CMake管理的库需要用<code>find_package</code>进行导入,为了让<code>find_package</code>能正确找到对应的库,需要再准备一个<code>MathFunctionsConfig.cmake</code>文件,通常由模板生成,模板格式固定,内容如下</p>
<p><code>MathFunctions/Config.cmake.in</code></p>
<pre><code class="fenced-code-block language-cmake">@PACKAGE_INIT@
<span class="token keyword">include</span><span class="token punctuation">(</span><span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_LIST_DIR</span><span class="token punctuation">}</span></span>/MathFunctionsTargets.cmake"</span> <span class="token punctuation">)</span></code></pre>
<p><code>configure_package_config_file</code>根据模板生成<code>MathFunctionsConfig.cmake</code>文件。</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">include</span><span class="token punctuation">(</span>CMakePackageConfigHelpers<span class="token punctuation">)</span>
<span class="token function">configure_package_config_file</span><span class="token punctuation">(</span><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_SOURCE_DIR</span><span class="token punctuation">}</span>/Config.cmake.in
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span></span>/MathFunctionsConfig.cmake"</span>
INSTALL_DESTINATION <span class="token string">"lib/cmake/example"</span>
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
<span class="token punctuation">)</span></code></pre>
<p><strong>第五步</strong> 生成版本文件(非必需)</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token function">write_basic_package_version_file</span><span class="token punctuation">(</span>
<span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span></span>/MathFunctionsConfigVersion.cmake"</span>
<span class="token property">VERSION</span> <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MAJOR</span><span class="token punctuation">}</span></span>.<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">Tutorial_VERSION_MINOR</span><span class="token punctuation">}</span></span>"</span>
COMPATIBILITY AnyNewerVersion
<span class="token punctuation">)</span></code></pre>
<p><strong>第六步</strong> 安装生成文件</p>
<p><code>MathFunctions/CMakeLists.txt</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">install</span><span class="token punctuation">(</span>FILES
<span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span>/MathFunctionsConfig.cmake
<span class="token punctuation">${</span><span class="token variable">CMAKE_CURRENT_BINARY_DIR</span><span class="token punctuation">}</span>/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="第十二步-打包调试版和发行版">第十二步 打包调试版和发行版</h2>
<p>本节示例只针对单配置生成器。对多配置生成器如Visual Studio不生效。</p>
<p>CMake一个构建目录只能有一种配置分别为<code>Debug</code><code>Release</code><code>MinSizeRel</code><code>RelWithDebInfo</code></p>
<p>对于需要指定的不同版本,只需要在配置时指明即可</p>
<pre><code class="fenced-code-block language-shell"><span class="token comment"># 指定生成器、配置为Release版本</span>
cmake -G <span class="token string">"MinGW Makefiles"</span> -DCMAKE_BUILD_TYPE<span class="token operator">=</span>Release <span class="token punctuation">..</span>
<span class="token comment"># 使用默认生成器配置为Debug版</span>
cmake -DCMAKE_BUILD_TYPE<span class="token operator">=</span>Debug <span class="token punctuation">..</span></code></pre>
<p>如果需要让Debug版本生成的目标名称与Release版本不同可以使用<code>CMAKE_DEBUG_POSTFIX</code>为Debug版设置后缀。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">CMAKE_DEBUG_POSTFIX</span> d<span class="token punctuation">)</span>
<span class="token keyword">add_executable</span><span class="token punctuation">(</span>Tutorial tutorial.cxx<span class="token punctuation">)</span>
<span class="token keyword">set_target_properties</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PROPERTIES</span> <span class="token property">DEBUG_POSTFIX</span> <span class="token punctuation">${</span><span class="token variable">CMAKE_DEBUG_POSTFIX</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>这样一来该目标及其依赖的目标生成的文件都会带有后缀<code>d</code></p>
<p> 通常来说会把Debug版与Release版分别放入两个<code>debug</code><code>release</code>目录中。如果只需要打包一版本,到对应目录中直接运行<code>cpack</code>即可。如果需要同时打包两个版本的内容,则在<code>debug</code><code>release</code>同级目录下新建一个<code>MultiCPackConfig.cmake</code>文件,内容如下</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">include</span><span class="token punctuation">(</span><span class="token string">"release/CPackConfig.cmake"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>CPACK_INSTALL_CMAKE_PROJECTS
<span class="token string">"debug;Tutorial;libSqrtLibraryd.a;/"</span>
<span class="token string">"release;Tutorial;ALL;/"</span>
<span class="token punctuation">)</span></code></pre>
<p><code>CPACK_INSTALL_CMAKE_PROJECTS</code>用来指定要打包的内容可以有多项每一项里有4部分内容分别为</p>
<ul>
<li>项目路径:指定要打包的项目所在的路径</li>
<li>项目名称:指定要打包的项目的名称</li>
<li>安装组件指定要打包的项目的安装组件。可以是ALL所有组件、DEFAULT默认组件或者是一个具体的组件名称</li>
<li>安装路径:指定要打包的项目的安装路径(相对整打包好的整个目录来说的)</li>
</ul>
<p>完成之后在本目录下执行</p>
<pre><code class="fenced-code-block language-shell">cpack --config MultiCPackConfig.cmake</code></pre>
<p>即可打包配置好的内容。</p>
<p>&nbsp;</p>
<h2 class="atx" id="练习-cmake-gui的使用">练习 cmake-gui的使用</h2>
<p>前面的配置与构建过程都是用命令CMake还提供了界面工具<code>cmake-gui</code>可以完成类似的工作。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="cmake基础知识补充">CMake基础知识补充</h1>
<p>前面Tutorial中只是简单过了一下涉及到的知识并没有对相关知识进行扩展。部分的内容主要为补充一些基础知识。由于CMake文档当中内容繁多本部分内容也不会全部涉及只挑选其中一部分进行讲解。有需要更深入了解的请自行查阅<a href="https://cmake.org/cmake/help/latest/index.html">官方文档</a></p>
<p>&nbsp;</p>
<h2 class="atx" id="cmake命令使用">CMake命令使用</h2>
<h3 class="atx" id="创建项目构建系统">创建项目构建系统</h3>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-cmake">cmake [&lt;options<span class="token punctuation">&gt;</span>] &lt;path-to-source | path-to-existing-build<span class="token punctuation">&gt;</span>
cmake [&lt;options<span class="token punctuation">&gt;</span>] -S &lt;path-to-source<span class="token punctuation">&gt;</span> -B &lt;path-to-build<span class="token punctuation">&gt;</span></code></pre>
<p><code>cmake [&lt;options&gt;] &lt;path-to-source&gt;</code></p>
<p>指定源文件(含有<code>CMakeLists.txt</code>文件的)目录,在当前目录下生成构建文件。指定目录可以是相对路径,也可以是绝对路径。</p>
<p><code>cmake [&lt;options&gt;] &lt;path-to-existing-build&gt;</code></p>
<p>指定已经生成构建文件(已经生成有<code>CMakeCache.txt</code>)的目录,重新加载(生成)。</p>
<p><code>cmake [&lt;options&gt;] -S &lt;path-to-source&gt; -B &lt;path-to-build&gt;</code></p>
<p>明确指定源文件目录与构建目录。</p>
<p>&nbsp;</p>
<p><strong>常用选项</strong></p>
<ul>
<li><p><strong>-S &lt;path-to-source&gt;</strong>:指定源文件根目录</p>
</li>
<li><p><strong>-B &lt;path-to-build&gt;</strong>:指定构建文件目录</p>
</li>
<li><p><strong>-G &lt;generator-name&gt;</strong>:指定生成器。具体支持哪些生成器可用</p>
<pre><code class="fenced-code-block language-shell">cmake --help</code></pre>
<p>查看。</p>
</li>
</ul>
<p>具体示例:</p>
<pre><code class="fenced-code-block language-shell"><span class="token comment"># 指定生成器为MinGW Makefiles生成mingw32-make的Makefile文件</span>
<span class="token comment"># 指定源文件根目录为src构建目录为build</span>
cmake -G <span class="token string">"MinGW Makefiles"</span> -S src -B build</code></pre>
<p>&nbsp;</p>
<h3 class="atx" id="构建项目">构建项目</h3>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-cmake">cmake --build &lt;dir<span class="token punctuation">&gt;</span> [&lt;options<span class="token punctuation">&gt;</span>] [-- &lt;build-tool-options<span class="token punctuation">&gt;</span>]</code></pre>
<p><code>cmake --build &lt;dir&gt;</code></p>
<p>&lt;dir&gt;为上述生成了构建文件的目录。生成器对应的构建工具来构建项目。</p>
<pre><code class="fenced-code-block language-cmake">cmake --build .</code></pre>
<p>&nbsp;</p>
<p><strong>常用选项</strong></p>
<ul>
<li><p><strong>-j [&lt;jobs&gt;], --parallel [&lt;jobs&gt;]</strong>:指定构建时的线程数,可以开启多线程构建提升速度</p>
<pre><code class="fenced-code-block language-shell">cmake --build <span class="token builtin class-name">.</span> -j <span class="token number">4</span>
cmake --build <span class="token builtin class-name">.</span> --parallel <span class="token number">4</span></code></pre>
</li>
<li><p><strong>-t &lt;tgt&gt;..., --target &lt;tgt&gt;...</strong>:指定构建目标。</p>
<pre><code class="fenced-code-block language-shell"><span class="token comment"># 指定目标为clean</span>
cmake --build <span class="token builtin class-name">.</span> -t clean
<span class="token comment"># 指定构建目标为install</span>
cmake --build <span class="token builtin class-name">.</span> --target <span class="token function">install</span></code></pre>
</li>
<li><p><strong>--clean-first</strong>构建前先clean</p>
</li>
</ul>
<p>使用<code>cmake --build</code>可以查看相关帮助信息。</p>
<p>&nbsp;</p>
<h3 class="atx" id="安装">安装</h3>
<p>安装已构建好的项目</p>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-shell">cmake --install <span class="token operator">&lt;</span>dir<span class="token operator">&gt;</span> <span class="token punctuation">[</span><span class="token operator">&lt;</span>options<span class="token operator">&gt;</span><span class="token punctuation">]</span></code></pre>
<ul>
<li><code>dir</code>为项目构建目录</li>
<li><code>options</code>安装选项</li>
</ul>
<p>常用选项</p>
<ul>
<li>*<em>--config &lt;cfg&gt; *</em> 对于多配置的项目,用于指定需要安装的配置</li>
<li><strong>--prefix &lt;prefix&gt;</strong> 指定安装目录</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="运行脚本">运行脚本</h3>
<p>CMake在一定程度上也可以算是一种编程语言。但是前面执行对应的代码都需要建立一个项目提供CMakeLists.txt文件再生成构建文件步骤比较多。</p>
<p>尤其是在学习阶段有时候可能只是想看一下里面一些内容运行是什么效果这样做就有点麻烦了。CMake提供了一种直接执行脚本的方式即先建立一个<code>&lt;filename&gt;.cmake</code>的脚本,再通过以下命令来执行。</p>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-shell">cmake <span class="token punctuation">[</span>-D <span class="token operator">&lt;</span>var<span class="token operator">&gt;=</span><span class="token operator">&lt;</span>value<span class="token operator">&gt;</span><span class="token punctuation">]</span><span class="token punctuation">..</span>. -P <span class="token operator">&lt;</span>cmake-script-file<span class="token operator">&gt;</span> <span class="token punctuation">[</span>-- <span class="token operator">&lt;</span>unparsed-options<span class="token operator">&gt;</span><span class="token punctuation">..</span>.<span class="token punctuation">]</span>
<span class="token comment"># 简写</span>
cmake -P <span class="token operator">&lt;</span>cmake-script-file<span class="token operator">&gt;</span></code></pre>
<p>示例</p>
<pre><code class="fenced-code-block language-shell">cmake -P learn.cmake</code></pre>
<p>&nbsp;</p>
<h3 class="atx" id="运行命令行工具">运行命令行工具</h3>
<p>CMake提供了一系列命令行工具如文件复制删除、哈希值计算等<code>cmake -E</code>可查看相关帮助。</p>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-shell">cmake -E <span class="token operator">&lt;</span>command<span class="token operator">&gt;</span> <span class="token punctuation">[</span><span class="token operator">&lt;</span>options<span class="token operator">&gt;</span><span class="token punctuation">]</span></code></pre>
<p>示例</p>
<pre><code class="fenced-code-block language-shell"><span class="token comment"># 以JSON格式输出CMake功能</span>
cmake -E capabilities
<span class="token comment"># 计算文件MD5值</span>
cmake -E md5sum tutorial.cxx
<span class="token comment"># 如果文件有改动则复制</span>
cmake -E copy_if_different file1.txt build/file2.txt</code></pre>
<p>更多命令详见<a href="https://cmake.org/cmake/help/latest/manual/cmake.1.html#run-a-command-line-tool">官方文档</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="cmake指令">CMake指令</h2>
<h3 class="atx" id="脚本指令">脚本指令</h3>
<h4 class="atx" id="message">message</h4>
<p>用于输出信息。</p>
<p><strong>用法</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 普通消息 &lt;mode&gt; 部分可以省略</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>[&lt;mode<span class="token punctuation">&gt;</span>] <span class="token string">"message text"</span> ...<span class="token punctuation">)</span>
<span class="token comment"># 状态消息</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>&lt;checkState<span class="token punctuation">&gt;</span> <span class="token string">"message text"</span> ...<span class="token punctuation">)</span>
<span class="token comment"># 配置日志</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>CONFIGURE_LOG &lt;text<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span></code></pre>
<p><code>&lt;mode&gt;</code>常用选项有如下几种</p>
<ul>
<li><code>FATAL_ERROR</code>CMake错误会终止往下执行</li>
<li><code>SEND_ERROR</code>CMake错误会继续执行但会跳过一些文件的生成</li>
<li><code>WARNING</code>:输出警告信息,不会终止执行</li>
<li><code>NOTICE</code>:一些需要注意的提示信息</li>
<li><code>DEBUG</code>:输出调试信息</li>
<li><code>STATUS</code>:输出当前状态信息</li>
</ul>
<p>更多选项与例子见<a href="https://cmake.org/cmake/help/latest/command/message.html">官方文档</a></p>
<p><code>&lt;checkState&gt;</code>选项有以下三种</p>
<ul>
<li><code>CHECK_START</code>:开始检测</li>
<li><code>CHECK_PASS</code>:检测通过</li>
<li><code>CHECK_FAIL</code>:检测不通过</li>
</ul>
<p>&nbsp;</p>
<h4 class="atx" id="变量定义与取消">变量定义与取消</h4>
<p><strong>定义普通变量</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> &lt;value<span class="token punctuation">&gt;</span>... [PARENT_SCOPE]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>PARENT_SCOPE</code>会将该变量定义到父作用域。并且变量值在当前作用域不可用。</li>
</ul>
<p><strong>修改环境变量</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span><span class="token variable">ENV</span>{&lt;variable<span class="token punctuation">&gt;</span><span class="token punctuation">}</span> [&lt;value<span class="token punctuation">&gt;</span>]<span class="token punctuation">)</span></code></pre>
<p><strong>定义Cache Entry</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> &lt;value<span class="token punctuation">&gt;</span>... <span class="token variable">CACHE</span> &lt;type<span class="token punctuation">&gt;</span> &lt;docstring<span class="token punctuation">&gt;</span> [FORCE]<span class="token punctuation">)</span></code></pre>
<ul>
<li><p><code>type</code>为类型,有以下几种</p>
<ul>
<li><p><code>BOOL</code>布尔<code>ON/OFF</code>值。<code>cmake-gui</code>中为复选框</p>
</li>
<li><p><code>FILEPATH</code>文件路径。<code>cmake-gui</code>中为文件选择窗口</p>
</li>
<li><p><code>PATH</code>目录路径,<code>cmake-gui</code>中为文件选择窗口</p>
</li>
<li><p><code>STRING</code>一行文字,<code>cmake-gui</code>中为文本输入框或下拉框</p>
<p>下拉框需要设置STRINGS属性多项可用空格或分号隔开</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>STRINT_TEST <span class="token string">""</span> <span class="token variable">CACHE</span> STRING <span class="token string">"Input text ..."</span><span class="token punctuation">)</span>
<span class="token keyword">set_property</span><span class="token punctuation">(</span><span class="token variable">CACHE</span> STRINT_TEST PROPERTY <span class="token property">STRINGS</span> hello world and you<span class="token punctuation">)</span></code></pre>
</li>
</ul>
</li>
<li><p><code>INTERNAL</code>一行文本,<code>cmake-gui</code>中不显示此类变量。用来存储处理过程中不变的内容。</p>
</li>
</ul>
<p><strong>变量取消定义</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">unset</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> [<span class="token variable">CACHE</span> | PARENT_SCOPE]<span class="token punctuation">)</span>
<span class="token keyword">unset</span><span class="token punctuation">(</span><span class="token variable">ENV</span>{&lt;variable<span class="token punctuation">&gt;</span><span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 取消环境变量</span>
<span class="token keyword">unset</span><span class="token punctuation">(</span><span class="token variable">ENV</span>{JAVA_HOME<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment"># 取消Cache Entry变量</span>
<span class="token keyword">unset</span><span class="token punctuation">(</span>FILE_PATH <span class="token variable">CACHE</span><span class="token punctuation">)</span>
<span class="token comment"># 取消上一级作用域的变量</span>
<span class="token keyword">unset</span><span class="token punctuation">(</span>VAR_OUT PARENT_SCOPE<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<h4 class="atx" id="条件判断">条件判断</h4>
<p><strong>语法</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span>&lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">elseif</span><span class="token punctuation">(</span>&lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span> <span class="token comment"># 可选、可重复</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment"># 可选</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p><strong>基础用法</strong></p>
<p><em>此部分测试不能用脚本运行的方式进行,会有一些其他问题</em></p>
<ul>
<li><p>常量判断</p>
<p><code>1</code>, <code>ON</code>, <code>YES</code>, <code>TRUE</code>, <code>Y</code>为真, <code>0</code>, <code>OFF</code>, <code>NO</code>, <code>FALSE</code>, <code>N</code>, <code>IGNORE</code>, <code>NOTFOUND</code>假,不区分大小写。如果不是这些常量,则会被当作变量或字符串对待。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span>YES<span class="token punctuation">)</span> <span class="token comment"># 把以上值填入括号测试</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 真<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 假<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p>变量判断</p>
<p>普通变量和环境变量都用这种方式。如果变量值不是为假的常量则为真。值为上述为假的或未定义则为假</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>VAR_1 hello world<span class="token punctuation">)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>VAR_1<span class="token punctuation">)</span> <span class="token comment"># 变量用做判断时不用加${}</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 真<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 假<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p>引号内字符串</p>
<p>除了引号内为上述为真的值,其他都为假</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">"HELLO"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 真<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 假<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
</li>
</ul>
<p><strong>逻辑运算</strong></p>
<p></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span>&lt;cond1<span class="token punctuation">&gt;</span> <span class="token operator">AND</span> &lt;cond2<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span>&lt;cond1<span class="token punctuation">&gt;</span> <span class="token operator">OR</span> &lt;cond2<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">NOT</span> &lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p><strong>其他常用判断</strong></p>
<ul>
<li><p><code>if(TARGET target-name)</code> 判断一个目标是否存在(由<code>add_executable()</code>, <code>add_library()</code>, <code>add_custom_target()</code>创建)</p>
</li>
<li><p><code>if(DEFINED &lt;name&gt;|CACHE{&lt;name&gt;}|ENV{&lt;name&gt;})</code>判断一个变量是否已定义</p>
</li>
<li><p><code>if(&lt;variable|string&gt; IN_LIST &lt;variable&gt;)</code>判断给定元素是否在列表中。列表中各项可用空格或分号隔开</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>M_LIST hello;world;and;not<span class="token punctuation">)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">"hello"</span> IN_LIST M_LIST<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 真<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS 假<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p><code>if(EXISTS path-to-file-or-directory)</code>判断文件或路径是否存在</p>
</li>
<li><p><code>if(&lt;variable|string&gt; MATCHES regex)</code>判断能否匹配上正则</p>
</li>
</ul>
<p>更多比较操作见<a href="https://cmake.org/cmake/help/v3.26/command/if.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="循环">循环</h4>
<p><strong>foreach</strong></p>
<p>用法一:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>&lt;loop_var<span class="token punctuation">&gt;</span> &lt;item_list<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 示例</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>M_LIST hello world and not<span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>WORD <span class="token punctuation">${</span>M_LIST<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token punctuation">${</span>WORD<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<ul>
<li><code>loop_var</code> 用来接收列表中每一项的变量</li>
<li><code>item_list</code>需要循环的列表,里面每一项用空格或者分号隔开</li>
</ul>
<p>可以用<code>continue()</code>结束本次循环,用<code>break()</code>终止循环</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>M_LIST hello world and how not <span class="token number">1</span> <span class="token number">2</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>WORD <span class="token punctuation">${</span>M_LIST<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">${</span>WORD<span class="token punctuation">}</span> <span class="token operator">STREQUAL</span> <span class="token string">"and"</span><span class="token punctuation">)</span>
<span class="token keyword">continue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">${</span>WORD<span class="token punctuation">}</span> <span class="token operator">STREQUAL</span> <span class="token string">"not"</span><span class="token punctuation">)</span>
<span class="token keyword">break</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token punctuation">${</span>WORD<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>用法二:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>&lt;loop_var<span class="token punctuation">&gt;</span> RANGE &lt;stop<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p>从0循环到<code>stop</code>指定的数,可以为负数</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>NUM RANGE -<span class="token number">11</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token punctuation">${</span>NUM<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>&lt;loop_var<span class="token punctuation">&gt;</span> RANGE &lt;start<span class="token punctuation">&gt;</span> &lt;stop<span class="token punctuation">&gt;</span> [&lt;step<span class="token punctuation">&gt;</span>]<span class="token punctuation">)</span></code></pre>
<p><code>start</code>指定的数循环到<code>stop</code>指定的数默认步长为1也可以指定步长。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>NUM RANGE <span class="token number">10</span> <span class="token number">20</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token punctuation">${</span>NUM<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>用法三:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>&lt;loop_var<span class="token punctuation">&gt;</span> IN [LISTS [&lt;lists<span class="token punctuation">&gt;</span>]] [ITEMS [&lt;items<span class="token punctuation">&gt;</span>]]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>LISTS</code>后面可以跟一个或多个用分号或空格隔开的列表,会分别循环取出每个列表中的每一项</li>
<li><code>ITEMS</code>后面可以放上多项内容,循环也会取出每一项</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>A <span class="token number">0</span>;<span class="token number">1</span>;<span class="token number">3</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>B <span class="token number">2</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>C <span class="token string">"4 5"</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>D <span class="token number">6</span>;<span class="token number">7</span> <span class="token number">8</span><span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>E <span class="token string">""</span><span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>X IN LISTS A B C D E ITEMS <span class="token punctuation">${</span>A<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"X=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">X</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>用法四:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">foreach</span><span class="token punctuation">(</span>&lt;loop_var<span class="token punctuation">&gt;</span>... IN ZIP_LISTS &lt;lists<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p>用指定变量循环多个列表</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">list</span><span class="token punctuation">(</span>APPEND English one two three four<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND Bahasa satu dua tiga<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND Chinese 一 二 三 四 五 六<span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>num IN ZIP_LISTS English Bahasa Chinese<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"num_0=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">num_0</span><span class="token punctuation">}</span></span>, num_1=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">num_1</span><span class="token punctuation">}</span></span>, num_2=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">num_2</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>en ba ch IN ZIP_LISTS English Bahasa Chinese<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"en=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">en</span><span class="token punctuation">}</span></span>, ba=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ba</span><span class="token punctuation">}</span></span>, ch=<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ch</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p><strong>while循环</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">while</span><span class="token punctuation">(</span>&lt;condition<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endwhile</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p><code>condition</code>为真时循环,真假的处理情况与<code>if()</code>相同。可以用<code>continue()</code>结束本次循环,用<code>break()</code>终止循环</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>i <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token keyword">while</span><span class="token punctuation">(</span>i <span class="token operator">LESS</span> <span class="token number">10</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span><span class="token string">"i = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">i</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">math</span><span class="token punctuation">(</span>EXPR i <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">i</span><span class="token punctuation">}</span></span> + 1"</span><span class="token punctuation">)</span>
<span class="token keyword">endwhile</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h4 class="atx" id="字符串操作">字符串操作</h4>
<p><strong>查找与替换</strong></p>
<p>查找:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>FIND &lt;string<span class="token punctuation">&gt;</span> &lt;substring<span class="token punctuation">&gt;</span> &lt;output_variable<span class="token punctuation">&gt;</span> [REVERSE]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>string</code>文本内容</li>
<li><code>substring</code>需要在文本内容中查找的子串</li>
<li><code>output_variable</code>存放子串第一次出现的索引,查找不到则为-1只针对单字节字符多字节字符会返回字节数据的索引</li>
<li><code>REVERSE</code>如果写上,则从文本末尾开始查找</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>FIND <span class="token string">"Hello World Hello World Hello World"</span> <span class="token string">"Hello2"</span> index REVERSE<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token punctuation">${</span>index<span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
<p>替换:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REPLACE &lt;match_string<span class="token punctuation">&gt;</span> &lt;replace_string<span class="token punctuation">&gt;</span> &lt;output_variable<span class="token punctuation">&gt;</span> &lt;input<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>match_string</code>需要被替换的内容</li>
<li><code>replace_string</code>用来替换的内容</li>
<li><code>output_variable</code>存放替换后的结果</li>
<li><code>input</code>原始文本,可以有多项</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REPLACE <span class="token string">"Hello"</span> <span class="token string">"好"</span> result <span class="token string">"Hello World"</span> <span class="token string">"Nod Hello "</span> <span class="token string">" And what"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>正则匹配</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REGEX MATCH &lt;regular_expression<span class="token punctuation">&gt;</span> &lt;output_variable<span class="token punctuation">&gt;</span> &lt;input<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token keyword">string</span><span class="token punctuation">(</span>REGEX MATCHALL &lt;regular_expression<span class="token punctuation">&gt;</span> &lt;output_variable<span class="token punctuation">&gt;</span> &lt;input<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>regular_expression</code>正则表达式</li>
<li><code>output_variable</code>存放匹配结果</li>
<li><code>input</code>原始文本,可以有多项,匹配前会被拼接到一起</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REGEX MATCH [<span class="token number">0</span>-<span class="token number">9</span>] result <span class="token string">"hello123world456hello444cmake"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">string</span><span class="token punctuation">(</span>REGEX MATCHALL [<span class="token number">0</span>-<span class="token number">9</span>] result <span class="token string">"hello123world456hello444cmake"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>正则替换</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REGEX REPLACE &lt;regular_expression<span class="token punctuation">&gt;</span> &lt;replacement_expression<span class="token punctuation">&gt;</span> &lt;output_variable<span class="token punctuation">&gt;</span> &lt;input<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>regular_expression</code>正则表达式</li>
<li><code>replacement_expression</code>替换内容</li>
<li><code>output_variable</code>存放结果</li>
<li><code>input</code>原始文本,可以有多项,匹配前会被拼接到一起</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>REGEX REPLACE [<span class="token number">0</span>-<span class="token number">9</span>] + result <span class="token string">"hello123world456hello444cmake"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p><strong>修改</strong></p>
<p>前后追加:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">string</span><span class="token punctuation">(</span>APPEND &lt;string_variable<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token keyword">string</span><span class="token punctuation">(</span>PREPEND &lt;string_variable<span class="token punctuation">&gt;</span> [&lt;input<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span></code></pre>
<p>……</p>
<p>更多字符串操作见<a href="https://cmake.org/cmake/help/v3.26/command/string.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="列表操作">列表操作</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token comment"># 列表长度</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>LENGTH &lt;list<span class="token punctuation">&gt;</span> &lt;out-var<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 获取指定索引处的元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>GET &lt;list<span class="token punctuation">&gt;</span> &lt;element index<span class="token punctuation">&gt;</span> [&lt;index<span class="token punctuation">&gt;</span> ...] &lt;out-var<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 用指定符号连接列表中的每一项</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>JOIN &lt;list<span class="token punctuation">&gt;</span> &lt;glue<span class="token punctuation">&gt;</span> &lt;out-var<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 获取子列表</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>SUBLIST &lt;list<span class="token punctuation">&gt;</span> &lt;begin<span class="token punctuation">&gt;</span> &lt;length<span class="token punctuation">&gt;</span> &lt;out-var<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 查询指定元素索引,不存在返回-1</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>FIND &lt;list<span class="token punctuation">&gt;</span> &lt;value<span class="token punctuation">&gt;</span> &lt;out-var<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 往列表后追加内容</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>APPEND &lt;list<span class="token punctuation">&gt;</span> [&lt;element<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 用正则筛选列表内容</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>FILTER &lt;list<span class="token punctuation">&gt;</span> {INCLUDE | EXCLUDE<span class="token punctuation">}</span> REGEX &lt;regex<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 在指定的位置插入元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>INSERT &lt;list<span class="token punctuation">&gt;</span> &lt;index<span class="token punctuation">&gt;</span> [&lt;element<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 移出末尾一个或多个元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>POP_BACK &lt;list<span class="token punctuation">&gt;</span> [&lt;out-var<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 移出头部一个或多个元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>POP_FRONT &lt;list<span class="token punctuation">&gt;</span> [&lt;out-var<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 向前追加元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>PREPEND &lt;list<span class="token punctuation">&gt;</span> [&lt;element<span class="token punctuation">&gt;</span>...]<span class="token punctuation">)</span>
<span class="token comment"># 删除指定值的元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>REMOVE_ITEM &lt;list<span class="token punctuation">&gt;</span> &lt;value<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span>
<span class="token comment"># 删除指定索引位置的元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>REMOVE_AT &lt;list<span class="token punctuation">&gt;</span> &lt;index<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span>
<span class="token comment"># 删除重复的元素</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>REMOVE_DUPLICATES &lt;list<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 对列表每项进行一些操作</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM &lt;list<span class="token punctuation">&gt;</span> &lt;ACTION<span class="token punctuation">&gt;</span> [&lt;SELECTOR<span class="token punctuation">&gt;</span>] [OUTPUT_VARIABLE &lt;output variable<span class="token punctuation">&gt;</span>]<span class="token punctuation">)</span>
<span class="token comment"># 逆序列表</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>REVERSE &lt;list<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token comment"># 排序</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>SORT &lt;list<span class="token punctuation">&gt;</span> [COMPARE &lt;compare<span class="token punctuation">&gt;</span>] [CASE &lt;case<span class="token punctuation">&gt;</span>] [ORDER &lt;order<span class="token punctuation">&gt;</span>]<span class="token punctuation">)</span></code></pre>
<p><code>TRANSFORM</code>中的<code>ACTION</code>有以下操作</p>
<ul>
<li><p><code>APPEND</code>, <code>PREPEND</code>:为每一项向前或向后追加内容</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS APPEND .exe<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p><code>TOUPPER</code>, <code>TOLOWER</code>:转换大小写</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS TOLOWER<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p><code>STRIP</code>:去除头尾空格</p>
</li>
<li><p><code>GENEX_STRIP</code>:去除生成器表达式</p>
</li>
<li><p><code>REPLACE</code>:正则替换</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS REPLACE [<span class="token number">0</span>-<span class="token number">9</span>] <span class="token string">"X"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
</ul>
<p><code>SELECTOR</code>用来决定需要对哪些元素进行操作</p>
<ul>
<li><p><code>AT</code>: 按索引指定需要操作的元素</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM &lt;list<span class="token punctuation">&gt;</span> &lt;ACTION<span class="token punctuation">&gt;</span> AT &lt;index<span class="token punctuation">&gt;</span> [&lt;index<span class="token punctuation">&gt;</span> ...] ...<span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS TOLOWER AT <span class="token number">0</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p><code>FOR</code>:用指定起点、终点、步长的方式进行操作</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM &lt;list<span class="token punctuation">&gt;</span> &lt;ACTION<span class="token punctuation">&gt;</span> FOR &lt;start<span class="token punctuation">&gt;</span> &lt;stop<span class="token punctuation">&gt;</span> [&lt;step<span class="token punctuation">&gt;</span>] ...<span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS TOLOWER FOR <span class="token number">0</span> <span class="token number">10</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
<li><p><code>REGEX</code>: 用正则匹配来决定需要进行操作的</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM &lt;list<span class="token punctuation">&gt;</span> &lt;ACTION<span class="token punctuation">&gt;</span> REGEX &lt;regular_expression<span class="token punctuation">&gt;</span> ...<span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>LS AA <span class="token number">11</span> <span class="token number">11</span> B <span class="token number">22</span> <span class="token number">11</span> C <span class="token number">33</span> D <span class="token number">11</span> <span class="token number">44</span> E<span class="token punctuation">)</span>
<span class="token keyword">list</span><span class="token punctuation">(</span>TRANSFORM LS APPEND .exe REGEX [A-Z]<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">LS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
</li>
</ul>
<p>更多详情见<a href="https://cmake.org/cmake/help/v3.26/command/list.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="数学表达式">数学表达式</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">math</span><span class="token punctuation">(</span>EXPR &lt;variable<span class="token punctuation">&gt;</span> <span class="token string">"&lt;expression&gt;"</span> [OUTPUT_FORMAT &lt;format<span class="token punctuation">&gt;</span>]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>variable</code>:运算结果</li>
<li><code>expression</code>:数学表达式</li>
<li><code>format</code>:输出格式,值为<code>DECIMAL</code>十进制和<code>HEXADECIMAL</code>十六进制</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">math</span><span class="token punctuation">(</span>EXPR value <span class="token string">"100 * 100"</span> OUTPUT_FORMAT DECIMAL<span class="token punctuation">)</span>
<span class="token keyword">math</span><span class="token punctuation">(</span>EXPR value <span class="token string">"100 * 0xA"</span> OUTPUT_FORMAT HEXADECIMAL<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<h4 class="atx" id="系统信息查询">系统信息查询</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_host_system_information</span><span class="token punctuation">(</span>RESULT &lt;variable<span class="token punctuation">&gt;</span> QUERY &lt;key<span class="token punctuation">&gt;</span> ...<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>variable</code>存放查询结果</li>
<li><code>key</code>需要查询的信息,可以为多项,空格隔开</li>
</ul>
<p>示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_host_system_information</span><span class="token punctuation">(</span>RESULT info QUERY HOSTNAME OS_NAME<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">info</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>更多细节见<a href="https://cmake.org/cmake/help/v3.26/command/cmake_host_system_information.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="函数">函数</h4>
<p><strong>1. 函数定义</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>&lt;name<span class="token punctuation">&gt;</span> [&lt;arg1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<p><strong>2. 函数定义会创建一个作用域</strong></p>
<p>没有指定了变量的<code>PARENT_SCOPE</code>时,在函数内部修改变量值在外部无法访问。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>OUT_VAR <span class="token number">100</span><span class="token punctuation">)</span>
<span class="token keyword">function</span><span class="token punctuation">(</span>func arg1 arg2<span class="token punctuation">)</span>
<span class="token keyword">set</span><span class="token punctuation">(</span>OUT_VAR <span class="token number">11</span> PARENT_SCOPE<span class="token punctuation">)</span> <span class="token comment"># PARENT_SCOPE修改外部变量没有PARENT_SCOPE则修改不到外部变量</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"OUT_VAR IN func = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">OUT_VAR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span>func<span class="token punctuation">)</span>
<span class="token function">func</span><span class="token punctuation">(</span><span class="token number">1</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"OUT_VAR = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">OUT_VAR</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p><strong>3. 函数支持可变参数</strong></p>
<p>函数可以在定义的时候指定一些参数名,但在使用的时候可以传递比已定义参数数量多的数据。可以用以下几个变量来获取参数:</p>
<ul>
<li><code>ARGC</code> :参数数量</li>
<li><code>ARGV</code> :所有参数组成的列表</li>
<li><code>ARGN</code>:没有命名的参数列表</li>
<li><code>ARGV0,ARGV1,ARGV2,...ARGVn</code>分别表示第0、1、2、……n个参数</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>func arg1 arg2<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"ARGC = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ARGC</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"ARGV = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ARGV</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"ARGN = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ARGN</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"arg1 = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">arg1</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"arg2 = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">arg3</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"ARGV2 = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ARGV2</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>ARG IN LISTS ARGN<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"ARG = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">ARG</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endforeach</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span>func<span class="token punctuation">)</span>
<span class="token function">func</span><span class="token punctuation">(</span><span class="token number">1</span> <span class="token number">2</span> <span class="token number">3</span> <span class="token number">4</span> <span class="token number">5</span> <span class="token number">6</span> <span class="token number">7</span><span class="token punctuation">)</span></code></pre>
<p><strong>4. 参数含关键字的函数</strong></p>
<p>例如函数<code>target_link_library</code>中的<code>PUBLIC | PRIVATE | INTERFACE</code>即为关键字,如果需要在自定义函数中使用类似的关键字,需要用到<code>cmake_parse_arguments</code></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span>&lt;prefix<span class="token punctuation">&gt;</span> &lt;options<span class="token punctuation">&gt;</span> &lt;one_value_keywords<span class="token punctuation">&gt;</span> &lt;multi_value_keywords<span class="token punctuation">&gt;</span> &lt;args<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span>
<span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span>PARSE_ARGV &lt;N<span class="token punctuation">&gt;</span> &lt;prefix<span class="token punctuation">&gt;</span> &lt;options<span class="token punctuation">&gt;</span> &lt;one_value_keywords<span class="token punctuation">&gt;</span> &lt;multi_value_keywords<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p>第一种方式可以在函数和宏中使用,第二种方式只能在函数中使用。第二种方式自动从<code>ARGV</code>里获取函数参数值,从第<code>&lt;N&gt;</code>个参数开始解析。其他参数如下:</p>
<ul>
<li><code>prefix</code>:前缀,可以用<code>prefix_&lt;KEYWORD&gt;</code>的形式访问对应的参数值</li>
<li><code>options</code>:不接收数据的关键字列表</li>
<li><code>one_value_keywords</code>:接收一项数据的关键字列表</li>
<li><code>multi_value_keywords</code>:接收多项数据关键字列表</li>
<li><code>args</code>:函数的参数,可以直接放<code>${ARGV}</code><code>${ARGN}</code></li>
</ul>
<p>示例:</p>
<p>不接收数据的关键字函数</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>test_parse<span class="token punctuation">)</span>
<span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span><span class="token string">"CPA"</span> <span class="token string">"INSTALL_INCLUDE;INSTALL_LIB"</span> <span class="token string">""</span> <span class="token string">""</span> <span class="token punctuation">${</span>ARGV<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"INSTALL_INCLUDE = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_INSTALL_INCLUDE</span><span class="token punctuation">}</span></span> INSTALL_LIB = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_INSTALL_LIB</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">test_parse</span><span class="token punctuation">(</span>INSTALL_LIB<span class="token punctuation">)</span></code></pre>
<p>接收一项数据的关键字函数</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>test_parse<span class="token punctuation">)</span>
<span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span><span class="token string">"CPA"</span> <span class="token string">""</span> <span class="token string">"FILE"</span> <span class="token string">""</span> <span class="token punctuation">${</span>ARGV<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"FILE = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_FILE</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">test_parse</span><span class="token punctuation">(</span>FILE test.cpp<span class="token punctuation">)</span></code></pre>
<p>接收多项数据的关键字函数</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>test_parse<span class="token punctuation">)</span>
<span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span><span class="token string">"CPA"</span> <span class="token string">""</span> <span class="token string">""</span> <span class="token string">"LIBS"</span> <span class="token punctuation">${</span>ARGV<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"LIBS = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_LIBS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">test_parse</span><span class="token punctuation">(</span>LIBS libmath.a libpng.a libtool.a<span class="token punctuation">)</span></code></pre>
<p>综合示例</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">function</span><span class="token punctuation">(</span>test_parse<span class="token punctuation">)</span>
<span class="token keyword">cmake_parse_arguments</span><span class="token punctuation">(</span><span class="token string">"CPA"</span> <span class="token string">"INSTALL_INCLUDES;INSTALL_LIBS"</span> <span class="token string">"CONFIG_FILE"</span> <span class="token string">"LIBS;CPPFILES;HEADFILES"</span> <span class="token punctuation">${</span>ARGV<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"INSTALL_INCLUDES = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_INSTALL_INCLUDES</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"INSTALL_LIBS = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_INSTALL_LIBS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"CONFIG_FILE = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_CONFIG_FILE</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"LIBS = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_LIBS</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"CPPFILES = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_CPPFILES</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"HEADFILES = <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">CPA_HEADFILES</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endfunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">test_parse</span><span class="token punctuation">(</span>LIBS libmath.a libfun.a CONFIG_FILE config.cmake CPPFILES main.cpp hello.cpp INSTALL_LIBS<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="宏定义">宏定义</h4>
<p>CMake中宏指令定义与用法类似函数的定义与用法。区别类似于C语言中宏函数定义与普通函数定义。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">macro</span><span class="token punctuation">(</span>&lt;name<span class="token punctuation">&gt;</span> [&lt;arg1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
&lt;commands<span class="token punctuation">&gt;</span>
<span class="token keyword">endmacro</span><span class="token punctuation">(</span><span class="token punctuation">)</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">macro</span><span class="token punctuation">(</span>macrofun arg1 arg2<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">arg1</span><span class="token punctuation">}</span></span> - <span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">arg2</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">endmacro</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">macrofun</span><span class="token punctuation">(</span><span class="token number">100</span> hello<span class="token punctuation">)</span>
<span class="token function">MACROFUN</span><span class="token punctuation">(</span><span class="token number">200</span> nice<span class="token punctuation">)</span> <span class="token comment"># 不区分大小写</span>
<span class="token function">cmake_language</span><span class="token punctuation">(</span>CALL macrofun <span class="token number">300</span> Hug<span class="token punctuation">)</span> <span class="token comment"># 另外的调用方式</span></code></pre>
<p>宏定义中可变参数与关键字参数用法与函数相同。</p>
<p>宏定义与函数不同点:</p>
<ul>
<li>宏定义不会创建新的使作用域</li>
<li>函数中所有参数、包括<code>ARGC</code><code>ARGV</code>等都是变量,但宏定义中这些参数不是变量,因此不能用类似<code>if(DEFINED ...)</code>的形式来检测宏定义中对应的参数是否已定义</li>
<li>宏定义的调用类似于把宏的内容直接复制到调用的地方</li>
</ul>
<p>&nbsp;</p>
<h4 class="atx" id="configure_file">configure_file</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">configure_file</span><span class="token punctuation">(</span>&lt;input<span class="token punctuation">&gt;</span> &lt;output<span class="token punctuation">&gt;</span>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS | FILE_PERMISSIONS &lt;perms<span class="token punctuation">&gt;</span>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [<span class="token variable">UNIX</span>|DOS|<span class="token variable">WIN32</span>|LF|CRLF] ]<span class="token punctuation">)</span></code></pre>
<p>后续的参数分为三个部分:</p>
<ul>
<li>输出文件权限主要用于Linux及其他类Unix系统<ul>
<li><code>NO_SOURCE_PERMISSIONS</code>不使用源文件权限使用默认644权限</li>
<li><code>USE_SOURCE_PERMISSIONS</code>保持与源文件权限一致</li>
<li><code>FILE_PERMISSIONS</code>自定义权限</li>
</ul>
</li>
<li>模板处理行为<ul>
<li><code>COPYONLY</code>只复制,不进行变量替换</li>
<li><code>ESCAPE_QUOTES</code>是否对双引号进行转义。不能和<code>NEWLINE_STYLE</code>同时使用</li>
<li><code>@ONLY</code>只替换<code>@VAR@</code>形式的变量,<code>${VAR}</code>形式的不进行替换</li>
</ul>
</li>
<li>换行方式<ul>
<li><code>UNIX</code><code>LF</code><code>\n</code> 换行</li>
<li><code>DOS</code><code>WIN32</code><code>CRLF</code><code>\r\n</code> 换行</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<h4 class="atx" id="文件操作">文件操作</h4>
<p>文件读取</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">file</span><span class="token punctuation">(</span>READ &lt;filename<span class="token punctuation">&gt;</span> &lt;variable<span class="token punctuation">&gt;</span> [OFFSET &lt;offset<span class="token punctuation">&gt;</span>] [LIMIT &lt;max-in<span class="token punctuation">&gt;</span>] [HEX]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>filename</code>:要读取的文件名</li>
<li><code>variable</code>:保存读取内容的变量名</li>
<li><code>offset</code>:开始读的位置</li>
<li><code>max-in</code>:读取的字节数</li>
<li><code>HEX</code>:是否转为十六进制,在读取二进制文件时常用</li>
</ul>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">file</span><span class="token punctuation">(</span>READ config.h.in result OFFSET <span class="token number">15</span> LIMIT <span class="token number">20</span> HEX<span class="token punctuation">)</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>文件写入</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">file</span><span class="token punctuation">(</span>WRITE &lt;filename<span class="token punctuation">&gt;</span> &lt;content<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span> <span class="token comment"># 写入</span>
<span class="token keyword">file</span><span class="token punctuation">(</span>APPEND &lt;filename<span class="token punctuation">&gt;</span> &lt;content<span class="token punctuation">&gt;</span>...<span class="token punctuation">)</span> <span class="token comment"># 追加</span></code></pre>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">file</span><span class="token punctuation">(</span>APPEND config.h <span class="token string">"Hello Worl from cmake file"</span> <span class="token string">"123456 555"</span><span class="token punctuation">)</span></code></pre>
<p>更多文件操作见<a href="https://cmake.org/cmake/help/v3.26/command/file.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="路径操作">路径操作</h4>
<p>详细介绍及例子见<a href="https://cmake.org/cmake/help/v3.26/command/cmake_path.html">官方文档</a></p>
<p>一些示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set</span><span class="token punctuation">(</span>path <span class="token string">"./config.h"</span><span class="token punctuation">)</span>
<span class="token keyword">file</span><span class="token punctuation">(</span>REAL_PATH <span class="token punctuation">${</span>path<span class="token punctuation">}</span> path<span class="token punctuation">)</span> <span class="token comment"># 将相对路径转为绝对路径</span>
<span class="token function">cmake_path</span><span class="token punctuation">(</span>GET path EXTENSION result<span class="token punctuation">)</span> <span class="token comment"># 取出文件后缀部分</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span>
<span class="token function">cmake_path</span><span class="token punctuation">(</span>GET path FILENAME result<span class="token punctuation">)</span> <span class="token comment"># 取出文件名称部分</span>
<span class="token keyword">message</span><span class="token punctuation">(</span>STATUS <span class="token string">"<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">result</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<h4 class="atx" id="文件查找">文件查找</h4>
<p><strong>在指定路径下查找指定文件</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">find_file</span> <span class="token punctuation">(</span>&lt;VAR<span class="token punctuation">&gt;</span> name1 [path1 path2 ...]<span class="token punctuation">)</span></code></pre>
<ul>
<li><code>VAR</code>:存放查找结果,找到则为文件绝对路径,找不到则为<code>&lt;VAR&gt;-NOTFOUND</code></li>
<li><code>name1</code>:需要查找的文件名</li>
<li><code>path</code>:指定查找路径,可以有多个</li>
</ul>
<p>更多操作见<a href="https://cmake.org/cmake/help/v3.26/command/find_file.html">官方文档</a></p>
<p>&nbsp;</p>
<p><strong>在指定路径下查找指定的库文件</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">find_library</span> <span class="token punctuation">(</span>&lt;VAR<span class="token punctuation">&gt;</span> name1 [path1 path2 ...]<span class="token punctuation">)</span></code></pre>
<p>参数与操作与文件查找相同。不同点在于库文件名可以简写,如<code>libMathFunctions.a</code>可以写为<code>MathFunctions</code></p>
<p>更多操作见<a href="https://cmake.org/cmake/help/v3.26/command/find_library.html">官方文档</a></p>
<p>&nbsp;</p>
<p><strong>在指定路径下查找指定的目录</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">find_path</span> <span class="token punctuation">(</span>&lt;VAR<span class="token punctuation">&gt;</span> name1 [path1 path2 ...]<span class="token punctuation">)</span></code></pre>
<p>用法同上。更多操作见<a href="https://cmake.org/cmake/help/v3.26/command/find_path.html">官方文档</a></p>
<p>&nbsp;</p>
<h4 class="atx" id="find_package">find_package</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">find_package</span><span class="token punctuation">(</span>&lt;PackageName<span class="token punctuation">&gt;</span> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]] <span class="token punctuation">)</span></code></pre>
<ul>
<li><p><code>PackageName</code>:需要查找的库名</p>
</li>
<li><p><code>version</code>:版本号</p>
</li>
<li><p><code>EXACT</code>:是否要精确匹配版本号</p>
</li>
<li><p><code>REQUIRED</code>:是否为必需的,加上之后如果找不到则会报错</p>
</li>
<li><p><code>COMPONENTS</code>:对于分了很多组件的包,可以指定组件</p>
</li>
</ul>
<p>&nbsp;</p>
<h3 class="atx" id="项目指令">项目指令</h3>
<h4 class="atx" id="add_dependencies">add_dependencies</h4>
<p>添加同级目标之间的相互依赖,保证依赖先生成。</p>
<p>&nbsp;</p>
<h4 class="atx" id="add_custom_target">add_custom_target</h4>
<p>添加自定义目标。</p>
<p>&nbsp;</p>
<h4 class="atx" id="属性设置">属性设置</h4>
<p>设置</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_property</span><span class="token punctuation">(</span>&lt;GLOBAL |
DIRECTORY [&lt;dir<span class="token punctuation">&gt;</span>] |
TARGET [&lt;target1<span class="token punctuation">&gt;</span> ...] |
SOURCE [&lt;src1<span class="token punctuation">&gt;</span> ...]
[DIRECTORY &lt;dirs<span class="token punctuation">&gt;</span> ...]
[TARGET_DIRECTORY &lt;targets<span class="token punctuation">&gt;</span> ...] |
INSTALL [&lt;file1<span class="token punctuation">&gt;</span> ...] |
TEST [&lt;test1<span class="token punctuation">&gt;</span> ...] |
<span class="token variable">CACHE</span> [&lt;entry1<span class="token punctuation">&gt;</span> ...] <span class="token punctuation">&gt;</span>
[APPEND] [APPEND_STRING]
PROPERTY &lt;name<span class="token punctuation">&gt;</span> [&lt;value1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span></code></pre>
<p>读取</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">get_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span>
&lt;GLOBAL |
DIRECTORY [&lt;dir<span class="token punctuation">&gt;</span>] |
TARGET &lt;target<span class="token punctuation">&gt;</span> |
SOURCE &lt;source<span class="token punctuation">&gt;</span>
[DIRECTORY &lt;dir<span class="token punctuation">&gt;</span> | TARGET_DIRECTORY &lt;target<span class="token punctuation">&gt;</span>] |
INSTALL &lt;file<span class="token punctuation">&gt;</span> |
TEST &lt;test<span class="token punctuation">&gt;</span> |
<span class="token variable">CACHE</span> &lt;entry<span class="token punctuation">&gt;</span> |
VARIABLE <span class="token punctuation">&gt;</span>
PROPERTY &lt;name<span class="token punctuation">&gt;</span>
[SET | <span class="token operator">DEFINED</span> | BRIEF_DOCS | FULL_DOCS]<span class="token punctuation">)</span></code></pre>
<ul>
<li><p><code>SET</code>:将<code>&lt;variable&gt;</code>设为该属性是否已设置</p>
</li>
<li><p><code>DEFINED</code>:将<code>&lt;variable&gt;</code>设为该属性是否已定义</p>
</li>
</ul>
<p><strong>全局属性</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_property</span><span class="token punctuation">(</span>GLOBAL PROPERTY &lt;name<span class="token punctuation">&gt;</span> [&lt;value1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
<span class="token keyword">get_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> GLOBAL PROPERTY &lt;name<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token keyword">get_cmake_property</span><span class="token punctuation">(</span>&lt;var<span class="token punctuation">&gt;</span> &lt;property<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p><strong>目录属性</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_property</span><span class="token punctuation">(</span>DIRECTORY [&lt;dir<span class="token punctuation">&gt;</span>] PROPERTY &lt;name<span class="token punctuation">&gt;</span> [&lt;value1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
<span class="token keyword">set_directory_properties</span><span class="token punctuation">(</span><span class="token namespace">PROPERTIES</span> prop1 value1 [prop2 value2] ...<span class="token punctuation">)</span>
<span class="token keyword">get_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> DIRECTORY [&lt;dir<span class="token punctuation">&gt;</span>] PROPERTY &lt;name<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token keyword">get_directory_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> [DIRECTORY &lt;dir<span class="token punctuation">&gt;</span>] &lt;prop-name<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p><strong>目标属性</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_property</span><span class="token punctuation">(</span>TARGET &lt;target1<span class="token punctuation">&gt;</span> PROPERTY &lt;name<span class="token punctuation">&gt;</span> [&lt;value1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
<span class="token keyword">set_target_properties</span><span class="token punctuation">(</span>target1... <span class="token namespace">PROPERTIES</span> prop1 value1 prop2 value2 ...<span class="token punctuation">)</span>
<span class="token keyword">get_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> TARGET &lt;target<span class="token punctuation">&gt;</span> PROPERTY &lt;name<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token keyword">get_target_property</span><span class="token punctuation">(</span>&lt;VAR<span class="token punctuation">&gt;</span> target property<span class="token punctuation">)</span></code></pre>
<p><strong>源文件属性</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_property</span><span class="token punctuation">(</span>SOURCE [&lt;src1<span class="token punctuation">&gt;</span> ...] [DIRECTORY &lt;dirs<span class="token punctuation">&gt;</span> ...] [TARGET_DIRECTORY &lt;targets<span class="token punctuation">&gt;</span> ...] PROPERTY &lt;name<span class="token punctuation">&gt;</span> [&lt;value1<span class="token punctuation">&gt;</span> ...]<span class="token punctuation">)</span>
<span class="token keyword">set_source_files_properties</span><span class="token punctuation">(</span>&lt;files<span class="token punctuation">&gt;</span> ...
[DIRECTORY &lt;dirs<span class="token punctuation">&gt;</span> ...]
[TARGET_DIRECTORY &lt;targets<span class="token punctuation">&gt;</span> ...]
<span class="token namespace">PROPERTIES</span> &lt;prop1<span class="token punctuation">&gt;</span> &lt;value1<span class="token punctuation">&gt;</span>
[&lt;prop2<span class="token punctuation">&gt;</span> &lt;value2<span class="token punctuation">&gt;</span>] ...<span class="token punctuation">)</span>
<span class="token keyword">get_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> SOURCE &lt;source<span class="token punctuation">&gt;</span> PROPERTY &lt;name<span class="token punctuation">&gt;</span><span class="token punctuation">)</span>
<span class="token keyword">get_source_file_property</span><span class="token punctuation">(</span>&lt;variable<span class="token punctuation">&gt;</span> &lt;file<span class="token punctuation">&gt;</span>
[DIRECTORY &lt;dir<span class="token punctuation">&gt;</span> | TARGET_DIRECTORY &lt;target<span class="token punctuation">&gt;</span>]
&lt;property<span class="token punctuation">&gt;</span><span class="token punctuation">)</span></code></pre>
<p><strong>测试属性</strong></p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">set_tests_properties</span><span class="token punctuation">(</span>test1 [test2...] <span class="token namespace">PROPERTIES</span> prop1 value1 prop2 value2<span class="token punctuation">)</span>
<span class="token keyword">get_test_property</span><span class="token punctuation">(</span>test property VAR<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="添加预编译定义">添加预编译定义</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_compile_definitions</span><span class="token punctuation">(</span>&lt;definition<span class="token punctuation">&gt;</span> ...<span class="token punctuation">)</span>
<span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span>
&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items1...]
[&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items2...] ...]<span class="token punctuation">)</span></code></pre>
<p>可用生成器表达式。</p>
<p>示例:</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">target_compile_definitions</span><span class="token punctuation">(</span>Tutorial <span class="token namespace">PUBLIC</span> HAVE_MAX_NUM MAX_NUM=<span class="token number">100</span><span class="token punctuation">)</span>
<span class="token keyword">add_compile_definitions</span><span class="token punctuation">(</span>HAVE_MIN_NUM MIN_NUM=-<span class="token number">999</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="添加编译选项">添加编译选项</h4>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">add_compile_options</span><span class="token punctuation">(</span>&lt;option<span class="token punctuation">&gt;</span> ...<span class="token punctuation">)</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>&lt;target<span class="token punctuation">&gt;</span> [BEFORE]
&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items1...]
[&lt;<span class="token namespace">INTERFACE</span>|<span class="token namespace">PUBLIC</span>|<span class="token namespace">PRIVATE</span><span class="token punctuation">&gt;</span> [items2...] ...]<span class="token punctuation">)</span></code></pre>
<p>可用生成器表达式。</p>
<pre><code class="fenced-code-block language-cmake"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">MSVC</span><span class="token punctuation">)</span>
<span class="token keyword">add_compile_options</span><span class="token punctuation">(</span>/W4<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">add_compile_options</span><span class="token punctuation">(</span>-Wall -Wextra -Wpedantic<span class="token punctuation">)</span>
<span class="token keyword">endif</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">target_compile_options</span><span class="token punctuation">(</span>tutorial_compiler_flags <span class="token namespace">INTERFACE</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">gcc_like_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused&gt;&gt;"</span>
<span class="token string">"$&lt;<span class="token interpolation"><span class="token punctuation">${</span><span class="token variable">msvc_cxx</span><span class="token punctuation">}</span></span>:$&lt;BUILD_INTERFACE:-W3&gt;&gt;"</span>
<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="mark_as_advanced">mark_as_advanced</h4>
<p>将缓存变量设为高级,在<code>cmake-gui</code>需要选择高级才能看到。</p>
<h4 class="atx" id="target_sources">target_sources</h4>
<p>为目标添加源文件</p>
<p>&nbsp;</p>
<h3 class="atx" id="生成器表达式">生成器表达式</h3>
<h1 class="atx" id="下一步">下一步</h1>
<p>接下来该怎么学?</p>
<ul>
<li>重做CMake Tutorial尽量自己完成可以通过查文档复习、加深印象</li>
<li>读开源项目CMake文件的写法<a href="https://github.com/fffaraz/awesome-cpp">https://github.com/fffaraz/awesome-cpp</a></li>
<li>继续熟悉文档,对有兴趣的地方自行深入研究</li>
<li>在应用中学习通过使用CMake遇到问题之后针对性地学习</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
</article>
</body>
</html>