Files
makefile_cpp/Make/make_md.html
2023-04-13 14:02:08 +08:00

3553 lines
182 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>
<style>
@font-face {
font-family: octicons-link;
src: url(data:font/woff;charset=utf-8;base64,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) 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9naXRodWItbWFya2Rvd24tY3NzL2dpdGh1Yi1tYXJrZG93bi5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFDRSwwQkFBMEI7RUFDMUIsMkRBQXF0RTtBQUN2dEU7O0FBRUE7RUFDRSxxQkFBcUI7RUFDckIsa0JBQWtCO0VBQ2xCLDJCQUEyQjtBQUM3Qjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxjQUFjO0VBQ2Qsa0JBQWtCO0VBQ2xCLGtCQUFrQjtBQUNwQjs7QUFFQTtFQUNFLGFBQWE7QUFDZjs7QUFFQTs7Ozs7O0VBTUUsY0FBYztFQUNkLHNCQUFzQjtFQUN0QixrQkFBa0I7QUFDcEI7O0FBRUE7Ozs7OztFQU1FLHFCQUFxQjtBQUN2Qjs7QUFFQTs7Ozs7O0VBTUUsbUJBQW1CO0FBQ3JCOztBQUVBO0VBQ0UsMEJBQTBCO0VBQzFCLDhCQUE4QjtFQUM5QixjQUFjO0VBQ2QsZ0JBQWdCO0VBQ2hCLGtJQUFrSTtFQUNsSSxlQUFlO0VBQ2YsZ0JBQWdCO0VBQ2hCLHFCQUFxQjtBQUN2Qjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7O0VBRUUsY0FBYztBQUNoQjs7QUFFQTs7RUFFRSxjQUFjO0FBQ2hCOztBQUVBOztFQUVFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTs7Ozs7OztFQU9FLGNBQWM7QUFDaEI7O0FBRUE7O0VBRUUsY0FBYztBQUNoQjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSx5QkFBeUI7RUFDekIsY0FBYztBQUNoQjs7QUFFQTtFQUNFLHlCQUF5QjtFQUN6QixjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsYUFBYTtBQUNmOztBQUVBO0VBQ0UsY0FBYztFQUNkLGdCQUFnQjtBQUNsQjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7OztFQUdFLGNBQWM7RUFDZCxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFD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 */
</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>
/* stylelint-disable font-family-no-missing-generic-family-keyword */
@font-face {
font-family: 'KaTeX_AMS';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_AMS-Regular.73ea273a.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_AMS-Regular.d562e886.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_AMS-Regular.853be924.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Caligraphic';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Bold.a1abf90d.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Bold.d757c535.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Bold.7489a2fb.ttf") format('truetype');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Caligraphic';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Regular.d6484fce.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Regular.db074fa2.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Caligraphic-Regular.7e873d38.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Fraktur';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Bold.931d67ea.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Bold.354501ba.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Bold.4c761b37.ttf") format('truetype');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Fraktur';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Regular.172d3529.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Regular.6fdf0ac5.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Fraktur-Regular.ed305b54.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Main';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Bold.39890742.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Bold.0c3b8929.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Bold.8169508b.ttf") format('truetype');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Main';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-BoldItalic.20f389c4.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-BoldItalic.428978dc.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-BoldItalic.828abcb2.ttf") format('truetype');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_Main';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Italic.fe2176f7.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Italic.fd947498.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Italic.fa675e5e.ttf") format('truetype');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_Main';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Regular.f650f111.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Regular.4f35fbcc.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Main-Regular.9eba1d77.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Math';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-BoldItalic.dcbcbd93.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-BoldItalic.3f07ed67.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-BoldItalic.bf2d440b.ttf") format('truetype');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_Math';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-Italic.6d3d25f4.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-Italic.96759856.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Math-Italic.8a5f9363.ttf") format('truetype');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_SansSerif';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Bold.95591a92.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Bold.b9cd458a.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Bold.5b49f499.ttf") format('truetype');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_SansSerif';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Italic.7d393d38.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Italic.8d593cfa.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Italic.b257a18c.ttf") format('truetype');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_SansSerif';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Regular.cd5e231e.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Regular.02271ec5.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_SansSerif-Regular.2f7bc363.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Script';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Script-Regular.c81d1b2a.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Script-Regular.073b3402.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Script-Regular.fc9ba524.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size1';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size1-Regular.6eec866c.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size1-Regular.0108e89c.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size1-Regular.6de7d4b5.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size2';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size2-Regular.2960900c.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size2-Regular.3a99e70a.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size2-Regular.57f5c183.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size3';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size3-Regular.e1951519.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size3-Regular.7947224e.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size3-Regular.8d6b6822.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size4';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size4-Regular.e418bf25.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size4-Regular.aeffd802.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Size4-Regular.4ad7c7e8.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Typewriter';
src: url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Typewriter-Regular.c295e7f7.woff2") format('woff2'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Typewriter-Regular.4c6b94fd.woff") format('woff'), url("file:///D:/Program%20Files/MarkText/resources/app.asar/dist/electron/fonts/KaTeX_Typewriter-Regular.c5c02d76.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
.katex {
font: normal 1.21em KaTeX_Main, Times New Roman, serif;
line-height: 1.2;
text-indent: 0;
text-rendering: auto;
}
.katex * {
-ms-high-contrast-adjust: none !important;
border-color: currentColor;
}
.katex .katex-version::after {
content: "0.15.2";
}
.katex .katex-mathml {
/* Accessibility hack to only show to screen readers
Found at: http://a11yproject.com/posts/how-to-hide-content/ */
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
}
.katex .katex-html {
/* \newline is an empty block at top level, between .base elements */
}
.katex .katex-html > .newline {
display: block;
}
.katex .base {
position: relative;
display: inline-block;
white-space: nowrap;
width: -webkit-min-content;
width: -moz-min-content;
width: min-content;
}
.katex .strut {
display: inline-block;
}
.katex .textbf {
font-weight: bold;
}
.katex .textit {
font-style: italic;
}
.katex .textrm {
font-family: KaTeX_Main;
}
.katex .textsf {
font-family: KaTeX_SansSerif;
}
.katex .texttt {
font-family: KaTeX_Typewriter;
}
.katex .mathnormal {
font-family: KaTeX_Math;
font-style: italic;
}
.katex .mathit {
font-family: KaTeX_Main;
font-style: italic;
}
.katex .mathrm {
font-style: normal;
}
.katex .mathbf {
font-family: KaTeX_Main;
font-weight: bold;
}
.katex .boldsymbol {
font-family: KaTeX_Math;
font-weight: bold;
font-style: italic;
}
.katex .amsrm {
font-family: KaTeX_AMS;
}
.katex .mathbb,
.katex .textbb {
font-family: KaTeX_AMS;
}
.katex .mathcal {
font-family: KaTeX_Caligraphic;
}
.katex .mathfrak,
.katex .textfrak {
font-family: KaTeX_Fraktur;
}
.katex .mathtt {
font-family: KaTeX_Typewriter;
}
.katex .mathscr,
.katex .textscr {
font-family: KaTeX_Script;
}
.katex .mathsf,
.katex .textsf {
font-family: KaTeX_SansSerif;
}
.katex .mathboldsf,
.katex .textboldsf {
font-family: KaTeX_SansSerif;
font-weight: bold;
}
.katex .mathitsf,
.katex .textitsf {
font-family: KaTeX_SansSerif;
font-style: italic;
}
.katex .mainrm {
font-family: KaTeX_Main;
font-style: normal;
}
.katex .vlist-t {
display: inline-table;
table-layout: fixed;
border-collapse: collapse;
}
.katex .vlist-r {
display: table-row;
}
.katex .vlist {
display: table-cell;
vertical-align: bottom;
position: relative;
}
.katex .vlist > span {
display: block;
height: 0;
position: relative;
}
.katex .vlist > span > span {
display: inline-block;
}
.katex .vlist > span > .pstrut {
overflow: hidden;
width: 0;
}
.katex .vlist-t2 {
margin-right: -2px;
}
.katex .vlist-s {
display: table-cell;
vertical-align: bottom;
font-size: 1px;
width: 2px;
min-width: 2px;
}
.katex .vbox {
display: inline-flex;
flex-direction: column;
align-items: baseline;
}
.katex .hbox {
display: inline-flex;
flex-direction: row;
width: 100%;
}
.katex .thinbox {
display: inline-flex;
flex-direction: row;
width: 0;
max-width: 0;
}
.katex .msupsub {
text-align: left;
}
.katex .mfrac > span > span {
text-align: center;
}
.katex .mfrac .frac-line {
display: inline-block;
width: 100%;
border-bottom-style: solid;
}
.katex .mfrac .frac-line,
.katex .overline .overline-line,
.katex .underline .underline-line,
.katex .hline,
.katex .hdashline,
.katex .rule {
min-height: 1px;
}
.katex .mspace {
display: inline-block;
}
.katex .llap,
.katex .rlap,
.katex .clap {
width: 0;
position: relative;
}
.katex .llap > .inner,
.katex .rlap > .inner,
.katex .clap > .inner {
position: absolute;
}
.katex .llap > .fix,
.katex .rlap > .fix,
.katex .clap > .fix {
display: inline-block;
}
.katex .llap > .inner {
right: 0;
}
.katex .rlap > .inner,
.katex .clap > .inner {
left: 0;
}
.katex .clap > .inner > span {
margin-left: -50%;
margin-right: 50%;
}
.katex .rule {
display: inline-block;
border: solid 0;
position: relative;
}
.katex .overline .overline-line,
.katex .underline .underline-line,
.katex .hline {
display: inline-block;
width: 100%;
border-bottom-style: solid;
}
.katex .hdashline {
display: inline-block;
width: 100%;
border-bottom-style: dashed;
}
.katex .sqrt > .root {
/* These values are taken from the definition of `\r@@t`,
`\mkern 5mu` and `\mkern -10mu`. */
margin-left: 0.27777778em;
margin-right: -0.55555556em;
}
.katex .sizing.reset-size1.size1,
.katex .fontsize-ensurer.reset-size1.size1 {
font-size: 1em;
}
.katex .sizing.reset-size1.size2,
.katex .fontsize-ensurer.reset-size1.size2 {
font-size: 1.2em;
}
.katex .sizing.reset-size1.size3,
.katex .fontsize-ensurer.reset-size1.size3 {
font-size: 1.4em;
}
.katex .sizing.reset-size1.size4,
.katex .fontsize-ensurer.reset-size1.size4 {
font-size: 1.6em;
}
.katex .sizing.reset-size1.size5,
.katex .fontsize-ensurer.reset-size1.size5 {
font-size: 1.8em;
}
.katex .sizing.reset-size1.size6,
.katex .fontsize-ensurer.reset-size1.size6 {
font-size: 2em;
}
.katex .sizing.reset-size1.size7,
.katex .fontsize-ensurer.reset-size1.size7 {
font-size: 2.4em;
}
.katex .sizing.reset-size1.size8,
.katex .fontsize-ensurer.reset-size1.size8 {
font-size: 2.88em;
}
.katex .sizing.reset-size1.size9,
.katex .fontsize-ensurer.reset-size1.size9 {
font-size: 3.456em;
}
.katex .sizing.reset-size1.size10,
.katex .fontsize-ensurer.reset-size1.size10 {
font-size: 4.148em;
}
.katex .sizing.reset-size1.size11,
.katex .fontsize-ensurer.reset-size1.size11 {
font-size: 4.976em;
}
.katex .sizing.reset-size2.size1,
.katex .fontsize-ensurer.reset-size2.size1 {
font-size: 0.83333333em;
}
.katex .sizing.reset-size2.size2,
.katex .fontsize-ensurer.reset-size2.size2 {
font-size: 1em;
}
.katex .sizing.reset-size2.size3,
.katex .fontsize-ensurer.reset-size2.size3 {
font-size: 1.16666667em;
}
.katex .sizing.reset-size2.size4,
.katex .fontsize-ensurer.reset-size2.size4 {
font-size: 1.33333333em;
}
.katex .sizing.reset-size2.size5,
.katex .fontsize-ensurer.reset-size2.size5 {
font-size: 1.5em;
}
.katex .sizing.reset-size2.size6,
.katex .fontsize-ensurer.reset-size2.size6 {
font-size: 1.66666667em;
}
.katex .sizing.reset-size2.size7,
.katex .fontsize-ensurer.reset-size2.size7 {
font-size: 2em;
}
.katex .sizing.reset-size2.size8,
.katex .fontsize-ensurer.reset-size2.size8 {
font-size: 2.4em;
}
.katex .sizing.reset-size2.size9,
.katex .fontsize-ensurer.reset-size2.size9 {
font-size: 2.88em;
}
.katex .sizing.reset-size2.size10,
.katex .fontsize-ensurer.reset-size2.size10 {
font-size: 3.45666667em;
}
.katex .sizing.reset-size2.size11,
.katex .fontsize-ensurer.reset-size2.size11 {
font-size: 4.14666667em;
}
.katex .sizing.reset-size3.size1,
.katex .fontsize-ensurer.reset-size3.size1 {
font-size: 0.71428571em;
}
.katex .sizing.reset-size3.size2,
.katex .fontsize-ensurer.reset-size3.size2 {
font-size: 0.85714286em;
}
.katex .sizing.reset-size3.size3,
.katex .fontsize-ensurer.reset-size3.size3 {
font-size: 1em;
}
.katex .sizing.reset-size3.size4,
.katex .fontsize-ensurer.reset-size3.size4 {
font-size: 1.14285714em;
}
.katex .sizing.reset-size3.size5,
.katex .fontsize-ensurer.reset-size3.size5 {
font-size: 1.28571429em;
}
.katex .sizing.reset-size3.size6,
.katex .fontsize-ensurer.reset-size3.size6 {
font-size: 1.42857143em;
}
.katex .sizing.reset-size3.size7,
.katex .fontsize-ensurer.reset-size3.size7 {
font-size: 1.71428571em;
}
.katex .sizing.reset-size3.size8,
.katex .fontsize-ensurer.reset-size3.size8 {
font-size: 2.05714286em;
}
.katex .sizing.reset-size3.size9,
.katex .fontsize-ensurer.reset-size3.size9 {
font-size: 2.46857143em;
}
.katex .sizing.reset-size3.size10,
.katex .fontsize-ensurer.reset-size3.size10 {
font-size: 2.96285714em;
}
.katex .sizing.reset-size3.size11,
.katex .fontsize-ensurer.reset-size3.size11 {
font-size: 3.55428571em;
}
.katex .sizing.reset-size4.size1,
.katex .fontsize-ensurer.reset-size4.size1 {
font-size: 0.625em;
}
.katex .sizing.reset-size4.size2,
.katex .fontsize-ensurer.reset-size4.size2 {
font-size: 0.75em;
}
.katex .sizing.reset-size4.size3,
.katex .fontsize-ensurer.reset-size4.size3 {
font-size: 0.875em;
}
.katex .sizing.reset-size4.size4,
.katex .fontsize-ensurer.reset-size4.size4 {
font-size: 1em;
}
.katex .sizing.reset-size4.size5,
.katex .fontsize-ensurer.reset-size4.size5 {
font-size: 1.125em;
}
.katex .sizing.reset-size4.size6,
.katex .fontsize-ensurer.reset-size4.size6 {
font-size: 1.25em;
}
.katex .sizing.reset-size4.size7,
.katex .fontsize-ensurer.reset-size4.size7 {
font-size: 1.5em;
}
.katex .sizing.reset-size4.size8,
.katex .fontsize-ensurer.reset-size4.size8 {
font-size: 1.8em;
}
.katex .sizing.reset-size4.size9,
.katex .fontsize-ensurer.reset-size4.size9 {
font-size: 2.16em;
}
.katex .sizing.reset-size4.size10,
.katex .fontsize-ensurer.reset-size4.size10 {
font-size: 2.5925em;
}
.katex .sizing.reset-size4.size11,
.katex .fontsize-ensurer.reset-size4.size11 {
font-size: 3.11em;
}
.katex .sizing.reset-size5.size1,
.katex .fontsize-ensurer.reset-size5.size1 {
font-size: 0.55555556em;
}
.katex .sizing.reset-size5.size2,
.katex .fontsize-ensurer.reset-size5.size2 {
font-size: 0.66666667em;
}
.katex .sizing.reset-size5.size3,
.katex .fontsize-ensurer.reset-size5.size3 {
font-size: 0.77777778em;
}
.katex .sizing.reset-size5.size4,
.katex .fontsize-ensurer.reset-size5.size4 {
font-size: 0.88888889em;
}
.katex .sizing.reset-size5.size5,
.katex .fontsize-ensurer.reset-size5.size5 {
font-size: 1em;
}
.katex .sizing.reset-size5.size6,
.katex .fontsize-ensurer.reset-size5.size6 {
font-size: 1.11111111em;
}
.katex .sizing.reset-size5.size7,
.katex .fontsize-ensurer.reset-size5.size7 {
font-size: 1.33333333em;
}
.katex .sizing.reset-size5.size8,
.katex .fontsize-ensurer.reset-size5.size8 {
font-size: 1.6em;
}
.katex .sizing.reset-size5.size9,
.katex .fontsize-ensurer.reset-size5.size9 {
font-size: 1.92em;
}
.katex .sizing.reset-size5.size10,
.katex .fontsize-ensurer.reset-size5.size10 {
font-size: 2.30444444em;
}
.katex .sizing.reset-size5.size11,
.katex .fontsize-ensurer.reset-size5.size11 {
font-size: 2.76444444em;
}
.katex .sizing.reset-size6.size1,
.katex .fontsize-ensurer.reset-size6.size1 {
font-size: 0.5em;
}
.katex .sizing.reset-size6.size2,
.katex .fontsize-ensurer.reset-size6.size2 {
font-size: 0.6em;
}
.katex .sizing.reset-size6.size3,
.katex .fontsize-ensurer.reset-size6.size3 {
font-size: 0.7em;
}
.katex .sizing.reset-size6.size4,
.katex .fontsize-ensurer.reset-size6.size4 {
font-size: 0.8em;
}
.katex .sizing.reset-size6.size5,
.katex .fontsize-ensurer.reset-size6.size5 {
font-size: 0.9em;
}
.katex .sizing.reset-size6.size6,
.katex .fontsize-ensurer.reset-size6.size6 {
font-size: 1em;
}
.katex .sizing.reset-size6.size7,
.katex .fontsize-ensurer.reset-size6.size7 {
font-size: 1.2em;
}
.katex .sizing.reset-size6.size8,
.katex .fontsize-ensurer.reset-size6.size8 {
font-size: 1.44em;
}
.katex .sizing.reset-size6.size9,
.katex .fontsize-ensurer.reset-size6.size9 {
font-size: 1.728em;
}
.katex .sizing.reset-size6.size10,
.katex .fontsize-ensurer.reset-size6.size10 {
font-size: 2.074em;
}
.katex .sizing.reset-size6.size11,
.katex .fontsize-ensurer.reset-size6.size11 {
font-size: 2.488em;
}
.katex .sizing.reset-size7.size1,
.katex .fontsize-ensurer.reset-size7.size1 {
font-size: 0.41666667em;
}
.katex .sizing.reset-size7.size2,
.katex .fontsize-ensurer.reset-size7.size2 {
font-size: 0.5em;
}
.katex .sizing.reset-size7.size3,
.katex .fontsize-ensurer.reset-size7.size3 {
font-size: 0.58333333em;
}
.katex .sizing.reset-size7.size4,
.katex .fontsize-ensurer.reset-size7.size4 {
font-size: 0.66666667em;
}
.katex .sizing.reset-size7.size5,
.katex .fontsize-ensurer.reset-size7.size5 {
font-size: 0.75em;
}
.katex .sizing.reset-size7.size6,
.katex .fontsize-ensurer.reset-size7.size6 {
font-size: 0.83333333em;
}
.katex .sizing.reset-size7.size7,
.katex .fontsize-ensurer.reset-size7.size7 {
font-size: 1em;
}
.katex .sizing.reset-size7.size8,
.katex .fontsize-ensurer.reset-size7.size8 {
font-size: 1.2em;
}
.katex .sizing.reset-size7.size9,
.katex .fontsize-ensurer.reset-size7.size9 {
font-size: 1.44em;
}
.katex .sizing.reset-size7.size10,
.katex .fontsize-ensurer.reset-size7.size10 {
font-size: 1.72833333em;
}
.katex .sizing.reset-size7.size11,
.katex .fontsize-ensurer.reset-size7.size11 {
font-size: 2.07333333em;
}
.katex .sizing.reset-size8.size1,
.katex .fontsize-ensurer.reset-size8.size1 {
font-size: 0.34722222em;
}
.katex .sizing.reset-size8.size2,
.katex .fontsize-ensurer.reset-size8.size2 {
font-size: 0.41666667em;
}
.katex .sizing.reset-size8.size3,
.katex .fontsize-ensurer.reset-size8.size3 {
font-size: 0.48611111em;
}
.katex .sizing.reset-size8.size4,
.katex .fontsize-ensurer.reset-size8.size4 {
font-size: 0.55555556em;
}
.katex .sizing.reset-size8.size5,
.katex .fontsize-ensurer.reset-size8.size5 {
font-size: 0.625em;
}
.katex .sizing.reset-size8.size6,
.katex .fontsize-ensurer.reset-size8.size6 {
font-size: 0.69444444em;
}
.katex .sizing.reset-size8.size7,
.katex .fontsize-ensurer.reset-size8.size7 {
font-size: 0.83333333em;
}
.katex .sizing.reset-size8.size8,
.katex .fontsize-ensurer.reset-size8.size8 {
font-size: 1em;
}
.katex .sizing.reset-size8.size9,
.katex .fontsize-ensurer.reset-size8.size9 {
font-size: 1.2em;
}
.katex .sizing.reset-size8.size10,
.katex .fontsize-ensurer.reset-size8.size10 {
font-size: 1.44027778em;
}
.katex .sizing.reset-size8.size11,
.katex .fontsize-ensurer.reset-size8.size11 {
font-size: 1.72777778em;
}
.katex .sizing.reset-size9.size1,
.katex .fontsize-ensurer.reset-size9.size1 {
font-size: 0.28935185em;
}
.katex .sizing.reset-size9.size2,
.katex .fontsize-ensurer.reset-size9.size2 {
font-size: 0.34722222em;
}
.katex .sizing.reset-size9.size3,
.katex .fontsize-ensurer.reset-size9.size3 {
font-size: 0.40509259em;
}
.katex .sizing.reset-size9.size4,
.katex .fontsize-ensurer.reset-size9.size4 {
font-size: 0.46296296em;
}
.katex .sizing.reset-size9.size5,
.katex .fontsize-ensurer.reset-size9.size5 {
font-size: 0.52083333em;
}
.katex .sizing.reset-size9.size6,
.katex .fontsize-ensurer.reset-size9.size6 {
font-size: 0.5787037em;
}
.katex .sizing.reset-size9.size7,
.katex .fontsize-ensurer.reset-size9.size7 {
font-size: 0.69444444em;
}
.katex .sizing.reset-size9.size8,
.katex .fontsize-ensurer.reset-size9.size8 {
font-size: 0.83333333em;
}
.katex .sizing.reset-size9.size9,
.katex .fontsize-ensurer.reset-size9.size9 {
font-size: 1em;
}
.katex .sizing.reset-size9.size10,
.katex .fontsize-ensurer.reset-size9.size10 {
font-size: 1.20023148em;
}
.katex .sizing.reset-size9.size11,
.katex .fontsize-ensurer.reset-size9.size11 {
font-size: 1.43981481em;
}
.katex .sizing.reset-size10.size1,
.katex .fontsize-ensurer.reset-size10.size1 {
font-size: 0.24108004em;
}
.katex .sizing.reset-size10.size2,
.katex .fontsize-ensurer.reset-size10.size2 {
font-size: 0.28929605em;
}
.katex .sizing.reset-size10.size3,
.katex .fontsize-ensurer.reset-size10.size3 {
font-size: 0.33751205em;
}
.katex .sizing.reset-size10.size4,
.katex .fontsize-ensurer.reset-size10.size4 {
font-size: 0.38572806em;
}
.katex .sizing.reset-size10.size5,
.katex .fontsize-ensurer.reset-size10.size5 {
font-size: 0.43394407em;
}
.katex .sizing.reset-size10.size6,
.katex .fontsize-ensurer.reset-size10.size6 {
font-size: 0.48216008em;
}
.katex .sizing.reset-size10.size7,
.katex .fontsize-ensurer.reset-size10.size7 {
font-size: 0.57859209em;
}
.katex .sizing.reset-size10.size8,
.katex .fontsize-ensurer.reset-size10.size8 {
font-size: 0.69431051em;
}
.katex .sizing.reset-size10.size9,
.katex .fontsize-ensurer.reset-size10.size9 {
font-size: 0.83317261em;
}
.katex .sizing.reset-size10.size10,
.katex .fontsize-ensurer.reset-size10.size10 {
font-size: 1em;
}
.katex .sizing.reset-size10.size11,
.katex .fontsize-ensurer.reset-size10.size11 {
font-size: 1.19961427em;
}
.katex .sizing.reset-size11.size1,
.katex .fontsize-ensurer.reset-size11.size1 {
font-size: 0.20096463em;
}
.katex .sizing.reset-size11.size2,
.katex .fontsize-ensurer.reset-size11.size2 {
font-size: 0.24115756em;
}
.katex .sizing.reset-size11.size3,
.katex .fontsize-ensurer.reset-size11.size3 {
font-size: 0.28135048em;
}
.katex .sizing.reset-size11.size4,
.katex .fontsize-ensurer.reset-size11.size4 {
font-size: 0.32154341em;
}
.katex .sizing.reset-size11.size5,
.katex .fontsize-ensurer.reset-size11.size5 {
font-size: 0.36173633em;
}
.katex .sizing.reset-size11.size6,
.katex .fontsize-ensurer.reset-size11.size6 {
font-size: 0.40192926em;
}
.katex .sizing.reset-size11.size7,
.katex .fontsize-ensurer.reset-size11.size7 {
font-size: 0.48231511em;
}
.katex .sizing.reset-size11.size8,
.katex .fontsize-ensurer.reset-size11.size8 {
font-size: 0.57877814em;
}
.katex .sizing.reset-size11.size9,
.katex .fontsize-ensurer.reset-size11.size9 {
font-size: 0.69453376em;
}
.katex .sizing.reset-size11.size10,
.katex .fontsize-ensurer.reset-size11.size10 {
font-size: 0.83360129em;
}
.katex .sizing.reset-size11.size11,
.katex .fontsize-ensurer.reset-size11.size11 {
font-size: 1em;
}
.katex .delimsizing.size1 {
font-family: KaTeX_Size1;
}
.katex .delimsizing.size2 {
font-family: KaTeX_Size2;
}
.katex .delimsizing.size3 {
font-family: KaTeX_Size3;
}
.katex .delimsizing.size4 {
font-family: KaTeX_Size4;
}
.katex .delimsizing.mult .delim-size1 > span {
font-family: KaTeX_Size1;
}
.katex .delimsizing.mult .delim-size4 > span {
font-family: KaTeX_Size4;
}
.katex .nulldelimiter {
display: inline-block;
width: 0.12em;
}
.katex .delimcenter {
position: relative;
}
.katex .op-symbol {
position: relative;
}
.katex .op-symbol.small-op {
font-family: KaTeX_Size1;
}
.katex .op-symbol.large-op {
font-family: KaTeX_Size2;
}
.katex .op-limits > .vlist-t {
text-align: center;
}
.katex .accent > .vlist-t {
text-align: center;
}
.katex .accent .accent-body {
position: relative;
}
.katex .accent .accent-body:not(.accent-full) {
width: 0;
}
.katex .overlay {
display: block;
}
.katex .mtable .vertical-separator {
display: inline-block;
min-width: 1px;
}
.katex .mtable .arraycolsep {
display: inline-block;
}
.katex .mtable .col-align-c > .vlist-t {
text-align: center;
}
.katex .mtable .col-align-l > .vlist-t {
text-align: left;
}
.katex .mtable .col-align-r > .vlist-t {
text-align: right;
}
.katex .svg-align {
text-align: left;
}
.katex svg {
display: block;
position: absolute;
width: 100%;
height: inherit;
fill: currentColor;
stroke: currentColor;
fill-rule: nonzero;
fill-opacity: 1;
stroke-width: 1;
stroke-linecap: butt;
stroke-linejoin: miter;
stroke-miterlimit: 4;
stroke-dasharray: none;
stroke-dashoffset: 0;
stroke-opacity: 1;
}
.katex svg path {
stroke: none;
}
.katex img {
border-style: none;
min-width: 0;
min-height: 0;
max-width: none;
max-height: none;
}
.katex .stretchy {
width: 100%;
display: block;
position: relative;
overflow: hidden;
}
.katex .stretchy::before,
.katex .stretchy::after {
content: "";
}
.katex .hide-tail {
width: 100%;
position: relative;
overflow: hidden;
}
.katex .halfarrow-left {
position: absolute;
left: 0;
width: 50.2%;
overflow: hidden;
}
.katex .halfarrow-right {
position: absolute;
right: 0;
width: 50.2%;
overflow: hidden;
}
.katex .brace-left {
position: absolute;
left: 0;
width: 25.1%;
overflow: hidden;
}
.katex .brace-center {
position: absolute;
left: 25%;
width: 50%;
overflow: hidden;
}
.katex .brace-right {
position: absolute;
right: 0;
width: 25.1%;
overflow: hidden;
}
.katex .x-arrow-pad {
padding: 0 0.5em;
}
.katex .cd-arrow-pad {
padding: 0 0.55556em 0 0.27778em;
}
.katex .x-arrow,
.katex .mover,
.katex .munder {
text-align: center;
}
.katex .boxpad {
padding: 0 0.3em;
}
.katex .fbox,
.katex .fcolorbox {
box-sizing: border-box;
border: 0.04em solid;
}
.katex .cancel-pad {
padding: 0 0.2em;
}
.katex .cancel-lap {
margin-left: -0.2em;
margin-right: -0.2em;
}
.katex .sout {
border-bottom-style: solid;
border-bottom-width: 0.08em;
}
.katex .angl {
box-sizing: border-box;
border-top: 0.049em solid;
border-right: 0.049em solid;
margin-right: 0.03889em;
}
.katex .anglpad {
padding: 0 0.03889em;
}
.katex .eqn-num::before {
counter-increment: katexEqnNo;
content: "(" counter(katexEqnNo) ")";
}
.katex .mml-eqn-num::before {
counter-increment: mmlEqnNo;
content: "(" counter(mmlEqnNo) ")";
}
.katex .mtr-glue {
width: 50%;
}
.katex .cd-vert-arrow {
display: inline-block;
position: relative;
}
.katex .cd-label-left {
display: inline-block;
position: absolute;
right: calc(50% + 0.3em);
text-align: left;
}
.katex .cd-label-right {
display: inline-block;
position: absolute;
left: calc(50% + 0.3em);
text-align: right;
}
.katex-display {
display: block;
margin: 1em 0;
text-align: center;
}
.katex-display > .katex {
display: block;
text-align: center;
white-space: nowrap;
}
.katex-display > .katex > .katex-html {
display: block;
position: relative;
}
.katex-display > .katex > .katex-html > .tag {
position: absolute;
right: 0;
}
.katex-display.leqno > .katex > .katex-html > .tag {
left: 0;
right: auto;
}
.katex-display.fleqn > .katex {
text-align: left;
padding-left: 2em;
}
body {
counter-reset: katexEqnNo mmlEqnNo;
}
/*# sourceURL=webpack://./node_modules/katex/dist/katex.css */
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL25vZGVfbW9kdWxlcy9rYXRleC9kaXN0L2thdGV4LmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxvRUFBb0U7QUFDcEU7RUFDRSx3QkFBd0I7RUFDeEIsZ0xBQThKO0VBQzlKLG1CQUFtQjtFQUNuQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLGdDQUFnQztFQUNoQyxnTEFBNks7RUFDN0ssaUJBQWlCO0VBQ2pCLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsZ0NBQWdDO0VBQ2hDLGdMQUFzTDtFQUN0TCxtQkFBbUI7RUFDbkIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSw0QkFBNEI7RUFDNUIsa0xBQWlLO0VBQ2pLLGlCQUFpQjtFQUNqQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLDRCQUE0QjtFQUM1QixtTEFBMEs7RUFDMUssbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UseUJBQXlCO0VBQ3pCLG1MQUF3SjtFQUN4SixpQkFBaUI7RUFDakIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSx5QkFBeUI7RUFDekIsbUxBQTBLO0VBQzFLLGlCQUFpQjtFQUNqQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHlCQUF5QjtFQUN6QixtTEFBOEo7RUFDOUosbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UseUJBQXlCO0VBQ3pCLG1MQUFpSztFQUNqSyxtQkFBbUI7RUFDbkIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSx5QkFBeUI7RUFDekIsbUxBQTBLO0VBQzFLLGlCQUFpQjtFQUNqQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHlCQUF5QjtFQUN6QixtTEFBOEo7RUFDOUosbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsOEJBQThCO0VBQzlCLG1MQUF1SztFQUN2SyxpQkFBaUI7RUFDakIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSw4QkFBOEI7RUFDOUIsbUxBQTZLO0VBQzdLLG1CQUFtQjtFQUNuQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLDhCQUE4QjtFQUM5QixtTEFBZ0w7RUFDaEwsbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsMkJBQTJCO0VBQzNCLG1MQUF1SztFQUN2SyxtQkFBbUI7RUFDbkIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSwwQkFBMEI7RUFDMUIsbUxBQW9LO0VBQ3BLLG1CQUFtQjtFQUNuQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLDBCQUEwQjtFQUMxQixtTEFBb0s7RUFDcEssbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsMEJBQTBCO0VBQzFCLG1MQUFvSztFQUNwSyxtQkFBbUI7RUFDbkIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSwwQkFBMEI7RUFDMUIsbUxBQW9LO0VBQ3BLLG1CQUFtQjtFQUNuQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLCtCQUErQjtFQUMvQixtTEFBbUw7RUFDbkwsbUJBQW1CO0VBQ25CLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0Usc0RBQXNEO0VBQ3RELGdCQUFnQjtFQUNoQixjQUFjO0VBQ2Qsb0JBQW9CO0FBQ3RCO0FBQ0E7RUFDRSx5Q0FBeUM7RUFDekMsMEJBQTBCO0FBQzVCO0FBQ0E7RUFDRSxpQkFBaUI7QUFDbkI7QUFDQTtFQUNFO3NFQUNvRTtFQUNwRSxrQkFBa0I7RUFDbEIsOEJBQThCO0VBQzlCLFVBQVU7RUFDVixTQUFTO0VBQ1QsV0FBVztFQUNYLFVBQVU7RUFDVixnQkFBZ0I7QUFDbEI7QUFDQTtFQUNFLG9FQUFvRTtBQUN0RTtBQUNBO0VBQ0UsY0FBYztBQUNoQjtBQUNBO0VBQ0Usa0JBQWtCO0VBQ2xCLHFCQUFxQjtFQUNyQixtQkFBbUI7RUFDbkIsMEJBQTBCO0VBQzFCLHVCQUF1QjtFQUN2QixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHFCQUFxQjtBQUN2QjtBQUNBO0VBQ0UsaUJBQWlCO0FBQ25CO0FBQ0E7RUFDRSxrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHVCQUF1QjtBQUN6QjtBQUNBO0VBQ0UsNEJBQTRCO0FBQzlCO0FBQ0E7RUFDRSw2QkFBNkI7QUFDL0I7QUFDQTtFQUNFLHVCQUF1QjtFQUN2QixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHVCQUF1QjtFQUN2QixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsdUJBQXVCO0VBQ3ZCLGlCQUFpQjtBQUNuQjtBQUNBO0VBQ0UsdUJBQXVCO0VBQ3ZCLGlCQUFpQjtFQUNqQixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHNCQUFzQjtBQUN4QjtBQUNBOztFQUVFLHNCQUFzQjtBQUN4QjtBQUNBO0VBQ0UsOEJBQThCO0FBQ2hDO0FBQ0E7O0VBRUUsMEJBQTBCO0FBQzVCO0FBQ0E7RUFDRSw2QkFBNkI7QUFDL0I7QUFDQTs7RUFFRSx5QkFBeUI7QUFDM0I7QUFDQTs7RUFFRSw0QkFBNEI7QUFDOUI7QUFDQTs7RUFFRSw0QkFBNEI7RUFDNUIsaUJBQWlCO0FBQ25CO0FBQ0E7O0VBRUUsNEJBQTRCO0VBQzVCLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsdUJBQXVCO0VBQ3ZCLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UscUJBQXFCO0VBQ3JCLG1CQUFtQjtFQUNuQix5QkFBeUI7QUFDM0I7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsbUJBQW1CO0VBQ25CLHNCQUFzQjtFQUN0QixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLGNBQWM7RUFDZCxTQUFTO0VBQ1Qsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSxxQkFBcUI7QUFDdkI7QUFDQTtFQUNFLGdCQUFnQjtFQUNoQixRQUFRO0FBQ1Y7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsbUJBQW1CO0VBQ25CLHNCQUFzQjtFQUN0QixjQUFjO0VBQ2QsVUFBVTtFQUNWLGNBQWM7QUFDaEI7QUFDQTtFQUNFLG9CQUFvQjtFQUNwQixzQkFBc0I7RUFDdEIscUJBQXFCO0FBQ3ZCO0FBQ0E7RUFDRSxvQkFBb0I7RUFDcEIsbUJBQW1CO0VBQ25CLFdBQVc7QUFDYjtBQUNBO0VBQ0Usb0JBQW9CO0VBQ3BCLG1CQUFtQjtFQUNuQixRQUFRO0VBQ1IsWUFBWTtBQUNkO0FBQ0E7RUFDRSxnQkFBZ0I7QUFDbEI7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UscUJBQXFCO0VBQ3JCLFdBQVc7RUFDWCwwQkFBMEI7QUFDNUI7QUFDQTs7Ozs7O0VBTUUsZUFBZTtBQUNqQjtBQUNBO0VBQ0UscUJBQXFCO0FBQ3ZCO0FBQ0E7OztFQUdFLFFBQVE7RUFDUixrQkFBa0I7QUFDcEI7QUFDQTs7O0VBR0Usa0JBQWtCO0FBQ3BCO0FBQ0E7OztFQUdFLHFCQUFxQjtBQUN2QjtBQUNBO0VBQ0UsUUFBUTtBQUNWO0FBQ0E7O0VBRUUsT0FBTztBQUNUO0FBQ0E7RUFDRSxpQkFBaUI7RUFDakIsaUJBQWlCO0FBQ25CO0FBQ0E7RUFDRSxxQkFBcUI7RUFDckIsZUFBZTtFQUNmLGtCQUFrQjtBQUNwQjtBQUNBOzs7RUFHRSxxQkFBcUI7RUFDckIsV0FBVztFQUNYLDBCQUEwQjtBQUM1QjtBQUNBO0VBQ0UscUJBQXFCO0VBQ3JCLFdBQVc7RUFDWCwyQkFBMkI7QUFDN0I7QUFDQTtFQUNFOytDQUM2QztFQUM3Qyx5QkFBeUI7RUFDekIsMkJBQTJCO0FBQzdCO0FBQ0E7O0VBRUUsY0FBYztBQUNoQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGNBQWM7QUFDaEI7QUFDQTs7RUFFRSxnQkFBZ0I7QUFDbEI7QUFDQTs7RUFFRSxpQkFBaUI7QUFDbkI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxjQUFjO0FBQ2hCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsY0FBYztBQUNoQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGlCQUFpQjtBQUNuQjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLGNBQWM7QUFDaEI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxpQkFBaUI7QUFDbkI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxjQUFjO0FBQ2hCO0FBQ0E7O0VBRUUsa0JBQWtCO0FBQ3BCO0FBQ0E7O0VBRUUsaUJBQWlCO0FBQ25CO0FBQ0E7O0VBRUUsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsaUJBQWlCO0FBQ25CO0FBQ0E7O0VBRUUsbUJBQW1CO0FBQ3JCO0FBQ0E7O0VBRUUsaUJBQWlCO0FBQ25CO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsY0FBYztBQUNoQjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGlCQUFpQjtBQUNuQjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLGNBQWM7QUFDaEI7QUFDQTs7RUFFRSxnQkFBZ0I7QUFDbEI7QUFDQTs7RUFFRSxpQkFBaUI7QUFDbkI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSxrQkFBa0I7QUFDcEI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxnQkFBZ0I7QUFDbEI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxpQkFBaUI7QUFDbkI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxjQUFjO0FBQ2hCO0FBQ0E7O0VBRUUsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsaUJBQWlCO0FBQ25CO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsa0JBQWtCO0FBQ3BCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsY0FBYztBQUNoQjtBQUNBOztFQUVFLGdCQUFnQjtBQUNsQjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHNCQUFzQjtBQUN4QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLHVCQUF1QjtBQUN6QjtBQUNBOztFQUVFLGNBQWM7QUFDaEI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSx1QkFBdUI7QUFDekI7QUFDQTs7RUFFRSxjQUFjO0FBQ2hCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsdUJBQXVCO0FBQ3pCO0FBQ0E7O0VBRUUsY0FBYztBQUNoQjtBQUNBO0VBQ0Usd0JBQXdCO0FBQzFCO0FBQ0E7RUFDRSx3QkFBd0I7QUFDMUI7QUFDQTtFQUNFLHdCQUF3QjtBQUMxQjtBQUNBO0VBQ0Usd0JBQXdCO0FBQzFCO0FBQ0E7RUFDRSx3QkFBd0I7QUFDMUI7QUFDQTtFQUNFLHdCQUF3QjtBQUMxQjtBQUNBO0VBQ0UscUJBQXFCO0VBQ3JCLGFBQWE7QUFDZjtBQUNBO0VBQ0Usa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSxrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLHdCQUF3QjtBQUMxQjtBQUNBO0VBQ0Usd0JBQXdCO0FBQzFCO0FBQ0E7RUFDRSxrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0Usa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSxRQUFRO0FBQ1Y7QUFDQTtFQUNFLGNBQWM7QUFDaEI7QUFDQTtFQUNFLHFCQUFxQjtFQUNyQixjQUFjO0FBQ2hCO0FBQ0E7RUFDRSxxQkFBcUI7QUFDdkI7QUFDQTtFQUNFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsZ0JBQWdCO0FBQ2xCO0FBQ0E7RUFDRSxpQkFBaUI7QUFDbkI7QUFDQTtFQUNFLGdCQUFnQjtBQUNsQjtBQUNBO0VBQ0UsY0FBYztFQUNkLGtCQUFrQjtFQUNsQixXQUFXO0VBQ1gsZUFBZTtFQUNmLGtCQUFrQjtFQUNsQixvQkFBb0I7RUFDcEIsa0JBQWtCO0VBQ2xCLGVBQWU7RUFDZixlQUFlO0VBQ2Ysb0JBQW9CO0VBQ3BCLHNCQUFzQjtFQUN0QixvQkFBb0I7RUFDcEIsc0JBQXNCO0VBQ3RCLG9CQUFvQjtFQUNwQixpQkFBaUI7QUFDbkI7QUFDQTtFQUNFLFlBQVk7QUFDZDtBQUNBO0VBQ0Usa0JBQWtCO0VBQ2xCLFlBQVk7RUFDWixhQUFhO0VBQ2IsZUFBZTtFQUNmLGdCQUFnQjtBQUNsQjtBQUNBO0VBQ0UsV0FBVztFQUNYLGNBQWM7RUFDZCxrQkFBa0I7RUFDbEIsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsV0FBVztBQUNiO0FBQ0E7RUFDRSxXQUFXO0VBQ1gsa0JBQWtCO0VBQ2xCLGdCQUFnQjtBQUNsQjtBQUNBO0VBQ0Usa0JBQWtCO0VBQ2xCLE9BQU87RUFDUCxZQUFZO0VBQ1osZ0JBQWdCO0FBQ2xCO0FBQ0E7RUFDRSxrQkFBa0I7RUFDbEIsUUFBUTtFQUNSLFlBQVk7RUFDWixnQkFBZ0I7QUFDbEI7QUFDQTtFQUNFLGtCQUFrQjtFQUNsQixPQUFPO0VBQ1AsWUFBWTtFQUNaLGdCQUFnQjtBQUNsQjtBQUNBO0VBQ0Usa0JBQWtCO0VBQ2xCLFNBQVM7RUFDVCxVQUFVO0VBQ1YsZ0JBQWdCO0FBQ2xCO0FBQ0E7RUFDRSxrQkFBa0I7RUFDbEIsUUFBUTtFQUNSLFlBQVk7RUFDWixnQkFBZ0I7QUFDbEI7QUFDQTtFQUNFLGdCQUFnQjtBQUNsQjtBQUNBO0VBQ0UsZ0NBQWdDO0FBQ2xDO0FBQ0E7OztFQUdFLGtCQUFrQjtBQUNwQjtBQUNBO0VBQ0UsZ0JBQWdCO0FBQ2xCO0FBQ0E7O0VBRUUsc0JBQXNCO0VBQ3RCLG9CQUFvQjtBQUN0QjtBQUNBO0VBQ0UsZ0JBQWdCO0FBQ2xCO0FBQ0E7RUFDRSxtQkFBbUI7RUFDbkIsb0JBQW9CO0FBQ3RCO0FBQ0E7RUFDRSwwQkFBMEI7RUFDMUIsMkJBQTJCO0FBQzdCO0FBQ0E7RUFDRSxzQkFBc0I7RUFDdEIseUJBQXlCO0VBQ3pCLDJCQUEyQjtFQUMzQix1QkFBdUI7QUFDekI7QUFDQTtFQUNFLG9CQUFvQjtBQUN0QjtBQUNBO0VBQ0UsNkJBQTZCO0VBQzdCLG9DQUFvQztBQUN0QztBQUNBO0VBQ0UsMkJBQTJCO0VBQzNCLGtDQUFrQztBQUNwQztBQUNBO0VBQ0UsVUFBVTtBQUNaO0FBQ0E7RUFDRSxxQkFBcUI7RUFDckIsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSxxQkFBcUI7RUFDckIsa0JBQWtCO0VBQ2xCLHdCQUF3QjtFQUN4QixnQkFBZ0I7QUFDbEI7QUFDQTtFQUNFLHFCQUFxQjtFQUNyQixrQkFBa0I7RUFDbEIsdUJBQXVCO0VBQ3ZCLGlCQUFpQjtBQUNuQjtBQUNBO0VBQ0UsY0FBYztFQUNkLGFBQWE7RUFDYixrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLGNBQWM7RUFDZCxrQkFBa0I7RUFDbEIsbUJBQW1CO0FBQ3JCO0FBQ0E7RUFDRSxjQUFjO0VBQ2Qsa0JBQWtCO0FBQ3BCO0FBQ0E7RUFDRSxrQkFBa0I7RUFDbEIsUUFBUTtBQUNWO0FBQ0E7RUFDRSxPQUFPO0VBQ1AsV0FBVztBQUNiO0FBQ0E7RUFDRSxnQkFBZ0I7RUFDaEIsaUJBQWlCO0FBQ25CO0FBQ0E7RUFDRSxrQ0FBa0M7QUFDcEMiLCJzb3VyY2VSb290IjoiIn0= */
</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"><h1 class="atx" id="学习环境搭建">学习环境搭建</h1>
<h3 class="atx" id="linux以ubuntu为倒">Linux以Ubuntu为倒</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> gcc g++ <span class="token function">make</span></code></pre>
<h3 class="atx" id="windows">Windows</h3>
<p>学习与演示过程以Windows为主Windows上装MinGW环境MinGW官网 <a href="https://www.mingw-w64.org/">https://www.mingw-w64.org/</a>
之前我们提过两个版本的环境,<strong>MingW-W64-builds</strong><strong>w64devkit</strong>
推荐使用<strong>w64devkit</strong>套件里面工具比较齐全还提供模拟了许多Linux命令用这个套件环境来学习可以保持在Linux与Windows上Makefile书写方式一致。
以下是w64devkit与其他包一些命令的区别</p>
<table>
<thead>
<tr>
<th align="center">w64devkit模拟Linux</th>
<th align="center">MingW-W64-builds或其他套件Windows&nbsp;cmd命令</th>
</tr>
</thead>
<tbody><tr>
<td align="center">make</td>
<td align="center">mingw32-make</td>
</tr>
<tr>
<td align="center">cc</td>
<td align="center">gcc</td>
</tr>
<tr>
<td align="center">rm</td>
<td align="center">del</td>
</tr>
<tr>
<td align="center">touch</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">ls</td>
<td align="center">dir</td>
</tr>
<tr>
<td align="center">sh</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">mv</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">cp</td>
<td align="center">copy/xcopy</td>
</tr>
<tr>
<td align="center">sed</td>
<td align="center"></td>
</tr>
</tbody></table>
<p>&nbsp;</p>
<h3 class="atx" id="学习材料">学习材料</h3>
<p>make官方文档 <a href="https://www.gnu.org/software/make/manual/make.html">https://www.gnu.org/software/make/manual/make.html</a></p>
<p>2048: <a href="https://github.com/plibither8/2048.cpp">https://github.com/plibither8/2048.cpp</a></p>
<p>sudoku: <a href="https://github.com/mayerui/sudoku">https://github.com/mayerui/sudoku</a>
&nbsp;
&nbsp;
&nbsp;
&nbsp;</p>
<h1 class="atx" id="makefile基础知识">Makefile基础知识</h1>
<h2 class="atx" id="make使用流程">make使用流程</h2>
<ol>
<li>准备好需要编译的源代码</li>
<li>编写Makefile文件</li>
<li>在命令行执行make命令</li>
</ol>
<p>&nbsp;
&nbsp;</p>
<h2 class="atx" id="最简单的makefile">最简单的Makefile</h2>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">hello</span><span class="token punctuation">:</span> hello.cpp
g++ hello.cpp -o hello <span class="token comment"># 开头必须为一个Tab不能为空格</span></code></pre>
<p><strong>但通常需要将编译与链接分开写,分为如下两步</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">hello</span><span class="token punctuation">:</span> hello.o
g++ hello.o -o hello
<span class="token target symbol">hello.o</span><span class="token punctuation">:</span> hello.cpp
g++ -c hello.cpp</code></pre>
<p>&nbsp;</p>
<p><strong>规则</strong>(Rules)一个Makefile文件由一条一条的规则构成一条规则结构如下</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">target … (目标)</span><span class="token punctuation">:</span> prerequisites …<span class="token punctuation">(</span>依赖<span class="token punctuation">)</span>
recipe<span class="token punctuation">(</span>方法<span class="token punctuation">)</span>
</code></pre>
<p>第二种写法</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">target … (目标)</span><span class="token punctuation">:</span> prerequisites …<span class="token punctuation">(</span>依赖<span class="token punctuation">)</span><span class="token punctuation">;</span> recipe<span class="token punctuation">(</span>方法<span class="token punctuation">)</span> <span class="token punctuation">;</span></code></pre>
<p>&nbsp;
&nbsp;
Make主要用于处理C和C++的编译工作但不只能处理C和C++,所有编译器/解释器能在命令行终端运行的编程语言都可以处理(例如Java、Python、 Golang....)。Make也不只能用来处理编程语言所有基于一些文件(依赖)的改变去更新另一些文件(目标)的工作都可以做。</p>
<p><strong>Make编译与打包Java程序示例</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">snake.jar</span> <span class="token punctuation">:</span> C.class Main.class SnakeFrame.class SnakePanel.class
jar -cvfe snake.jar Main *.class
<span class="token target symbol">C.class</span> <span class="token punctuation">:</span> C.java
javac C.java
<span class="token target symbol">Main.class</span> <span class="token punctuation">:</span> Main.java
javac Main.java
<span class="token target symbol">SnakeFrame.class</span> <span class="token punctuation">:</span> SnakeFrame.java
javac SnakeFrame.java
<span class="token target symbol">SnakePanel.class</span> <span class="token punctuation">:</span> SnakePanel.java
javac SnakePanel.java
<span class="token builtin-target builtin">.PHONY</span><span class="token punctuation">:</span> clean
<span class="token target symbol">clean</span><span class="token punctuation">:</span>
rm *.class *.jar</code></pre>
<p>&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;</p>
<h2 class="atx" id="makefile文件的命名与指定">Makefile文件的命名与指定</h2>
<p>Make会自动查找makefile文件查找顺序为GNUmakefile -&gt; makefile -&gt; Makefile</p>
<p><strong>GNUmakefile</strong>不建议使用因为只有GNU make会识别其他版本的make如BSD make, Windows nmake等不会识别如果只给GNU make使用的情况</p>
<p><strong>makefile</strong>可以使用GNU make和其他版本make识别</p>
<p><strong>Makefile</strong>:最常用,强烈建议使用</p>
<p>如果运行make的时候没有找到以上名字的文件则会报错这时候可以手动指定文件名</p>
<pre><code class="fenced-code-block language-shell"><span class="token function">make</span> -f mkfile <span class="token comment"># make -f &lt;filename&gt;</span>
<span class="token function">make</span> --file<span class="token operator">=</span>mkfile <span class="token comment"># make --file=&lt;filename&gt;</span></code></pre>
<blockquote>
<p>手动指定之后make就会使用指定的文件即使有Makefile或者makefile不会再自动使用</p>
</blockquote>
<p>&nbsp;
&nbsp;
&nbsp;</p>
<h2 class="atx" id="makefile文件内容组成">Makefile文件内容组成</h2>
<p>一个Makefile文件通常由五种类型的内容组成显式规则、隐式规则、变量定义、指令和注释</p>
<p><strong>显式规则</strong>(<em>explicit rules</em>):显式指明何时以及如何生成或更新目标文件,显式规则包括目标、依赖和更新方法三个部分</p>
<p><strong>隐式规则</strong>(<em>implicit rules</em>):根据文件自动推导如何从依赖生成或更新目标文件。</p>
<p><strong>变量定义</strong>(<em>variable definitions</em>)定议变量并指定值值都是字符串类似C语言中的宏定义(#define),在使用时将值展开到引用位置</p>
<p><strong>指令</strong>(<em>directives</em>)在make读取Makefile的过程中做一些特别的操作包括</p>
<ol>
<li><p>读取(包含)另一个makefile文件(类似C语言中的#include)</p>
</li>
<li><p>确定是否使用或略过makefile文件中的一部分内容(类似C语言中的#if)</p>
</li>
<li><p>定义多行变量</p>
</li>
</ol>
<p><strong>注释</strong>(<em>comments</em>):一行当中 # 后面的内容都是注释不会被make执行。make当中只有单行注释。如果需要用到#而不是注释,用\#。</p>
<p>&nbsp;
&nbsp;
&nbsp;
&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="一个稍微复杂的makefile">一个稍微复杂的Makefile</h2>
<p><img alt="" src="./img/1.png"></p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">sudoku</span><span class="token punctuation">:</span> block.o command.o input.o main.o scene.o test.o
g++ -o sudoku block.o command.o input.o main.o scene.o test.o
<span class="token target symbol">block.o</span><span class="token punctuation">:</span> block.cpp common.h block.h color.h
g++ -c block.cpp
<span class="token target symbol">command.o</span><span class="token punctuation">:</span> command.cpp scene.h common.h block.h command.h
g++ -c command.cpp
<span class="token target symbol">input.o</span><span class="token punctuation">:</span> input.cpp common.h utility.inl
g++ -c input.cpp
<span class="token target symbol">main.o</span><span class="token punctuation">:</span> main.cpp scene.h common.h block.h command.h input.h
g++ -c main.cpp
<span class="token target symbol">scene.o</span><span class="token punctuation">:</span> scene.cpp common.h scene.h block.h command.h utility.inl
g++ -c scene.cpp
<span class="token target symbol">test.o</span><span class="token punctuation">:</span> test.cpp test.h scene.h common.h block.h command.h
g++ -c test.cpp
<span class="token target symbol">hello.o</span><span class="token punctuation">:</span> hello.cpp
g++ -c hello.cpp
<span class="token target symbol">clean</span><span class="token punctuation">:</span>
rm block.o command.o input.o main.o scene.o test.o
rm sudoku.exe</code></pre>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">target … (目标)</span><span class="token punctuation">:</span> prerequisites …<span class="token punctuation">(</span>依赖<span class="token punctuation">)</span>
recipe<span class="token punctuation">(</span>方法<span class="token punctuation">)</span>
</code></pre>
<h2 class="atx" id="目标">目标</h2>
<ol>
<li><p>Makefile中会有很多目标但最终目标只有一个其他所有内容都是为这个最终目标服务的写Makefile的时候<strong>先写出最终目标,再依次解决总目标的依赖</strong></p>
</li>
<li><p>一般情况第一条规则中的目标会被确立为最终目标第一条规则默认会被make执行</p>
</li>
<li><p>通常来说目标是一个文件,一条规则的目的就是生成或更新目标文件。</p>
</li>
<li><p>make会根据目标文件和依赖文件最后修改时间判断是否需要执行更新目标文件的方法。如果目标文件不存在或者目标文件最后修改时间早于其中一个依赖文件最后修改时间则重新执行更新目标文件的方法。否则不会执行。</p>
</li>
<li><p>除了最终目标对应的更新方法默认会执行外如果Makefile中一个目标不是其他目标的依赖那么这个目标对应的规则不会自动执行。需要手动指定方法为</p>
<pre><code class="fenced-code-block language-makefile">make &lt;target&gt; <span class="token comment"># 如 make clean , make hello.o</span></code></pre>
</li>
<li><p>可以使用.DEFAULT_GOAL来修改默认最终目标</p>
<pre><code class="fenced-code-block language-makefile">.DEFAULT_GOAL <span class="token operator">=</span> main
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo all
<span class="token target symbol">main</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo main</code></pre>
</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="伪目标">伪目标</h2>
<p>如果一个标并不是一个文件则这个目标就是伪目标。例如前面的clean目标。如果说在当前目录下有一个文件名称和这个目标名称冲突了则这个目标就没法执行。这时候需要用到一个特殊的目标 .PHONY将上面的clean目标改写如下 </p>
<pre><code class="fenced-code-block language-makefile"><span class="token builtin-target builtin">.PHONY</span><span class="token punctuation">:</span> clean
<span class="token target symbol">clean</span><span class="token punctuation">:</span>
rm block.o command.o input.o main.o scene.o test.o
rm sudoku.exe</code></pre>
<p>这样即使当前目录下存在与目标同名的文件,该目标也能正常执行。</p>
<p><strong>伪目标的其他应用方式</strong></p>
<p>如果一条规则的依赖文件没有改动,则不会执行对应的更新方法。如果需要每次不论有没有改动都执行某一目标的更新方法,可以把对应的目标添加到.PHONY的依赖中例如下面这种方式则每次执行make都会更新test.o不管其依赖文件有没有改动</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">test.o</span><span class="token punctuation">:</span> test.cpp test.h
g++ -c test.cpp
<span class="token builtin-target builtin">.PHONY</span><span class="token punctuation">:</span> clean test.o</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="依赖">依赖</h2>
<h3 class="atx" id="依赖类型">依赖类型</h3>
<p><strong>普通依赖</strong></p>
<p>前面说过的这种形式都是普通依赖。直接列在目标后面。普通依赖有两个特点:</p>
<ol>
<li>如果这一依赖是由其他规则生成的文件,那么执行到这一目标前会先执行生成依赖的那一规则 </li>
<li>如果任何一个依赖文件修改时间比目标晚,那么就重新生成目标文件</li>
</ol>
<p><strong>order-only依赖</strong></p>
<p>依赖文件不存在时,会执行对应的方法生成,但依赖文件更新并不会导致目标文件的更新</p>
<p>如果目标文件已存在order-only依赖中的文件即使修改时间比目标文件晚目标文件也不会更新。</p>
<p>定义方法如下:</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">targets</span> <span class="token punctuation">:</span> normal-prerequisites <span class="token operator">|</span> order-only-prerequisites</code></pre>
<p>normal-prerequisites部分可以为空</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="指定依赖搜索路径">指定依赖搜索路径</h3>
<p>make默认在Makefile文件所在的目录下查找依赖文件如果找不到就会报错。这时候就需要手动指定搜索路径用VPATH变量或vpath指令。</p>
<p><strong>VPATH用法如下</strong></p>
<pre><code class="fenced-code-block language-makefile">VPATH <span class="token operator">=</span> &lt;dir1&gt;<span class="token punctuation">:</span>&lt;dir2&gt;<span class="token punctuation">:</span>&lt;dir3&gt;...
<span class="token comment"># 例如</span>
VPATH <span class="token operator">=</span> <span class="token keyword">include</span><span class="token punctuation">:</span>src</code></pre>
<p>多个目录之间冒号隔开这时make会在VPATH指定的这些目录里面查找依赖文件。</p>
<p><strong>vpath指令用法</strong></p>
<p>vpath比VPATH使用更灵活可以指定某个类型的文件在哪个目录搜索。</p>
<p>用法如下:</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">vpath</span> &lt;pattern&gt; &lt;directories&gt;
<span class="token keyword">vpath</span> %.h <span class="token keyword">include</span> <span class="token comment"># .h文件在include目录下查找</span>
<span class="token target symbol">vpath %.h include</span><span class="token punctuation">:</span>headers <span class="token comment"># .h文件在include或headers文件下查找</span>
<span class="token keyword">vpath</span> % src <span class="token comment"># 所有文件都在src下查找</span>
<span class="token keyword">vpath</span> hello.cpp src <span class="token comment"># hello.cpp文件在src查找</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="更新方法">更新方法</h2>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">target … (目标)</span><span class="token punctuation">:</span> prerequisites …<span class="token punctuation">(</span>依赖<span class="token punctuation">)</span>
recipe<span class="token punctuation">(</span>方法<span class="token punctuation">)</span>
</code></pre>
<h4 class="atx" id="关于执行终端">关于执行终端</h4>
<p>更新方法实际上是一些Shell指令通常以Tab开头或直接放在目标-依赖列表后面用分号隔开。这些指令都需要交给Shell执行所以需要符合Shell语法。默认使用的Shell是sh在Windows上如果没有安装sh.exe的话会自动查找使用cmd.exe之类的终端。这时有的指令写法例如循环语句与Linux不同需要注意。</p>
<p>可以通过SHELL变量手动指定Shell</p>
<pre><code class="fenced-code-block language-makefile">SHELL <span class="token operator">=</span> C<span class="token punctuation">:</span>/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
SHELL <span class="token operator">=</span> cmd.exe</code></pre>
<p>默认的执行方式为一条指令重新调用一个Shell进程来执行。有时为了提高性能或其他原因想让这个目标的所有指令都在同一进程中执行可以在Makefile中添加 .ONESHELL</p>
<pre><code class="fenced-code-block language-makefile"> <span class="token builtin-target builtin">.ONESHELL</span><span class="token punctuation">:</span></code></pre>
<p>这样所有指令都会在同一次Shell调用中执行</p>
<h4 class="atx" id="shell语句回显问题">Shell语句回显问题</h4>
<p>通常make在执行一条Shell语句前都会先打印这条语句如果不想打印可以在语句开头在@</p>
<pre><code class="fenced-code-block language-makefile"><span class="token operator">@</span>echo hello
<span class="token operator">@</span>g++ -o hello hello.cpp</code></pre>
<p>也可以使用.SILENT来指定哪些目标的更新方法指令不用打印</p>
<pre><code class="fenced-code-block language-makefile"><span class="token builtin-target builtin">.SILENT</span><span class="token punctuation">:</span> main all</code></pre>
<h4 class="atx" id="错误处理">错误处理</h4>
<p>如果一条规则当中包含多条Shell指令每条指令执行完之后make都会检查返回状态如果返回状态是0则执行成功继续执行下一条指令直到最后一条指令执行完成之后一条规则也就结束了。</p>
<p>如果过程中发生了错误即某一条指令的返回值不是0那么make就会终止执行当前规则中剩下的Shell指令。</p>
<p>例如</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">clean</span><span class="token punctuation">:</span>
rm main.o hello.o
rm main.exe</code></pre>
<p>这时如果第一条rm main.o hello.o出错第二条rm main.exe就不会执行。类似情况下希望make忽视错误继续下一条指令。在指令开头<code>-</code>可以达到这种效果。</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">clean</span><span class="token punctuation">:</span>
-rm main.o hello.o
-rm main.exe</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 class="atx" id="变量应用">变量应用</h2>
<p>Makefile中的变量有点类似C语言中的宏定义即用一个名称表示一串文本。但与C语言宏定义不同的是Makefile的变量值是可以改变的。变量定义之后可以在目标、依赖、方法等Makefile文件的任意地方进行引用。</p>
<blockquote>
<p>Makefile中的变量值只有一种类型 字符串</p>
</blockquote>
<p><strong>变量可以用来表示什么</strong></p>
<ul>
<li><p>文件名序列</p>
</li>
<li><p>编译选项</p>
</li>
<li><p>需要运行的程序</p>
</li>
<li><p>需要进行操作的路径</p>
</li>
<li><p>......</p>
</li>
</ul>
<h3 class="atx" id="变量定义与引用方式">变量定义与引用方式</h3>
<p><strong>定义方式</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token comment"># &lt;变量名&gt; = &lt;变量值&gt; &lt;变量名&gt; := &lt;变量值&gt; &lt;变量名&gt; ::= &lt;变量值&gt;</span>
files <span class="token operator">=</span> main.cpp hello.cpp
objects <span class="token operator">:=</span> main.o hello.o
<span class="token target symbol">var3</span> <span class="token operator">::=</span> main.o</code></pre>
<blockquote>
<p>变量名区分大小写,可以是任意字符串,不能含有":", "#", "="</p>
</blockquote>
<p><strong>使用方式</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token comment"># $(&lt;变量名&gt;) 或者 ${&lt;变量名&gt;}</span>
<span class="token target symbol">main.o</span> <span class="token punctuation">:</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span> <span class="token comment"># 或者 ${files}</span>
...</code></pre>
<blockquote>
<p>如果变量名只有一个字符,使用时可以不用括号,如$a, $b 但不建议这样用,不管是否只有一个字符都写成$(a), $(b)这种形式</p>
</blockquote>
<h3 class="atx" id="makefile读取过程">Makefile读取过程</h3>
<p>GNU make分两个阶段来执行Makefile第一阶段(读取阶段)</p>
<ul>
<li><p>读取Makefile文件的所有内容</p>
</li>
<li><p>根据Makefile的内容在程序内建立起变量</p>
</li>
<li><p>在程序内构建起显式规则、隐式规则</p>
</li>
<li><p>建立目标和依赖之间的依赖图</p>
</li>
</ul>
<p>第二阶段(目标更新阶段)</p>
<ul>
<li>用第一阶段构建起来的数据确定哪个目标需要更新然后执行对应的更新方法</li>
</ul>
<p>变量和函数的展开如果发生在第一阶段,就称作<strong>立即展开</strong>,否则称为<strong>延迟展开</strong>。立即展开的变量或函数在第一个阶段也就是Makefile被读取解析的时候就进行展开。延迟展开的变量或函数将会到用到的时候才会进行展开有以下两种情况</p>
<ul>
<li><p>在一个立即展开的表达式中用到</p>
</li>
<li><p>在第二个阶段中用到</p>
</li>
</ul>
<p><strong>显式规则中,目标和依赖部分都是立即展开,在更新方法中延迟展开</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="变量赋值">变量赋值</h3>
<h4 class="atx" id="递归展开赋值(延迟展开)">递归展开赋值(延迟展开)</h4>
<p>第一种方式就是直接使用<kbd>=</kbd>这种方式如果赋值的时候右边是其他变量引用或者函数调用之类的将不会做处理直接保留原样在使用到该变量的时候再来进行处理得到变量值Makefile执行的第二个阶段再进行变量展开得到变量值</p>
<pre><code class="fenced-code-block language-makefile">bar2 <span class="token operator">=</span> ThisIsBar2No.1
foo <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>bar<span class="token punctuation">)</span>
foo2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>bar2<span class="token punctuation">)</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>foo<span class="token punctuation">)</span> <span class="token comment"># Huh?</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>foo2<span class="token punctuation">)</span> <span class="token comment"># ThisIsBar2No.2</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>ugh<span class="token punctuation">)</span> <span class="token comment"># Huh?</span>
bar <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>ugh<span class="token punctuation">)</span>
ugh <span class="token operator">=</span> Huh?
bar2 <span class="token operator">=</span> ThisIsBar2No.2</code></pre>
<h4 class="atx" id="简单赋值立即展开">简单赋值(立即展开)</h4>
<p>简单赋值使用<kbd>:=</kbd><kbd>::=</kbd>这种方式如果等号右边是其他变量或者引用的话将会在赋值的时候就进行处理得到变量值。Makefile执行第一阶段进行变量展开</p>
<pre><code class="fenced-code-block language-makefile">bar2 <span class="token operator">:=</span> ThisIsBar2No.1
foo <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>bar<span class="token punctuation">)</span>
foo2 <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>bar2<span class="token punctuation">)</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>foo<span class="token punctuation">)</span> <span class="token comment"># 空串,没有内容</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>foo2<span class="token punctuation">)</span> <span class="token comment"># ThisIsBar2No.1</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>ugh<span class="token punctuation">)</span> <span class="token comment"># </span>
bar <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>ugh<span class="token punctuation">)</span>
ugh <span class="token operator">:=</span> Huh?
bar2 <span class="token operator">:=</span> ThisIsBar2No.2</code></pre>
<h4 class="atx" id="条件赋值">条件赋值</h4>
<p>条件赋值使用<kbd>?=</kbd>,如果变量已经定义过了(即已经有值了),那么就保持原来的值,如果变量还没赋值过,就把右边的值赋给变量。</p>
<pre><code class="fenced-code-block language-makefile">var1 <span class="token operator">=</span> 100
var1 <span class="token operator">?=</span> 200
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span> <span class="token comment"># 100 注释var1 = 100之后为200</span></code></pre>
<p><strong>练习</strong>试求a的值</p>
<pre><code class="fenced-code-block language-makefile">x <span class="token operator">=</span> hello
y <span class="token operator">=</span> world
a <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token variable">$</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span>
x <span class="token operator">=</span> y
y <span class="token operator">=</span> z
a <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span>
x <span class="token operator">=</span> y
y <span class="token operator">=</span> z
z <span class="token operator">=</span> u
a <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
x <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span>
y <span class="token operator">=</span> z
z <span class="token operator">=</span> Hello
a <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="追加">追加</h4>
<p>使用<kbd>+=</kbd>在变量已有的基础上追加内容</p>
<pre><code class="fenced-code-block language-makefile">files <span class="token operator">=</span> main.cpp
files <span class="token operator">+=</span> hello.cpp
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="shell运行赋值">Shell运行赋值</h4>
<p>使用<kbd>!=</kbd>运行一个Shell指令后将返回值赋给一个变量</p>
<pre><code class="fenced-code-block language-makefile">gcc_version <span class="token operator">!=</span> gcc --version
files <span class="token operator">!=</span> ls .</code></pre>
<blockquote>
<p>如果使用Windows需要注意这种赋值方式只适用于与Linux相同的Shell指令Windows独有的指令不能这样使用。</p>
</blockquote>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="定义多行变量">定义多行变量</h3>
<p>前面定义的变量都是单行的。</p>
<p>变量值有多行多用于定义shell指令</p>
<p><strong>语法</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">define</span> &lt;varable_name&gt; <span class="token comment"># 默认为 = </span>
<span class="token comment"># 变量内容</span>
<span class="token keyword">endef</span>
<span class="token keyword">define</span> &lt;varable_name&gt; <span class="token operator">:=</span>
<span class="token comment"># 变量内容</span>
<span class="token keyword">endef</span>
<span class="token keyword">define</span> &lt;varable_name&gt; <span class="token operator">+=</span>
<span class="token comment"># 变量内容</span>
<span class="token keyword">endef</span></code></pre>
<p>&nbsp;</p>
<p><strong>示例</strong></p>
<pre><code class="fenced-code-block language-makefile">echosomething <span class="token operator">=</span> <span class="token operator">@</span>echo This is the first line
<span class="token keyword">define</span> echosomething <span class="token operator">+=</span>
<span class="token operator">@</span>echo hello
<span class="token operator">@</span>echo world
<span class="token operator">@</span>echo 3
<span class="token keyword">endef</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token variable">$</span><span class="token punctuation">(</span>echosomething<span class="token punctuation">)</span></code></pre>
<h3 class="atx" id="取消变量">取消变量</h3>
<p>如果想清除一个变量,用以下方法</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">undefine</span> &lt;变量名&gt;<span class="token keyword">undefine</span> files, <span class="token keyword">undefine</span> objs</code></pre>
<h3 class="atx" id="环境变量的使用">环境变量的使用</h3>
<p>系统中的环境变量可以直接在Makefile中直接使用使用方法跟普通变量一样</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>USERNAME<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>JAVA_HOME<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>SystemRoot<span class="token punctuation">)</span></code></pre>
<h3 class="atx" id="变量替换引用">变量替换引用</h3>
<p>语法:<strong>$(var:a=b)</strong>意思是将变量var的值当中每一项结尾的a替换为b直接上例子</p>
<pre><code class="fenced-code-block language-makefile">files <span class="token operator">=</span> main.cpp hello.cpp
objs <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">:</span>.cpp<span class="token operator">=</span>.o<span class="token punctuation">)</span> <span class="token comment"># main.o hello.o</span>
<span class="token comment"># 另一种写法</span>
objs <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">:</span>%.cpp<span class="token operator">=</span>%.o<span class="token punctuation">)</span></code></pre>
<h3 class="atx" id="变量覆盖">变量覆盖</h3>
<p>所有在Makefile中的变量都可以在执行make时能过指定参数的方式进行覆盖。</p>
<pre><code class="fenced-code-block language-makefile">OverridDemo <span class="token operator">:=</span> ThisIsInMakefile
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>OverridDemo<span class="token punctuation">)</span></code></pre>
<p>如果直接执行</p>
<pre><code class="fenced-code-block language-shell"><span class="token function">make</span></code></pre>
<p>则上面的输出内容为<em>ThisIsInMakefile</em>但可以在执行make时指定参数</p>
<pre><code class="fenced-code-block language-shell"><span class="token function">make</span> <span class="token assign-left variable">OverridDemo</span><span class="token operator">=</span>ThisIsFromOutShell <span class="token comment"># 等号两边不能有空格</span>
<span class="token comment"># 如果变量值中有空格,需要用引号</span>
<span class="token function">make</span> <span class="token assign-left variable">OverridDemo</span><span class="token operator">=</span>“This Is From Out Shell”</code></pre>
<p>则输出OverridDemo的值是ThisIsFromOutShell或This Is From Out Shell。</p>
<p>用这样的命令参数会覆盖Makefile中对应变量的值如果不想被覆盖可以在变量前加上override指令override具有较高优先级不会被命令参数覆盖</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">override</span> OverridDemo <span class="token operator">:=</span> ThisIsInMakefile
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>OverridDemo<span class="token punctuation">)</span></code></pre>
<p>这样即使命令行指定参数</p>
<pre><code class="fenced-code-block language-shell"><span class="token function">make</span> <span class="token assign-left variable">OverridDemo</span><span class="token operator">=</span>ThisIsFromOutShell</code></pre>
<p>输出结果依然是ThisIsInMakefile</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="自动变量">自动变量</h3>
<p><strong>$@</strong>:①本条规则的目标名;②如果目标是归档文件的成员,则为归档文件名;③在多目标的模式规则中, 为导致本条规则方法执行的那个目标名;</p>
<p><strong>$&lt;</strong>:本条规则的第一个依赖名称</p>
<p><strong>$?</strong>:依赖中修改时间晚于目标文件修改时间的所有文件名,以空格隔开</p>
<p><strong>$^</strong>所有依赖文件名文件名不会重复不包含order-only依赖</p>
<p><strong>$+</strong>:类似上一个, 表示所有依赖文件名包括重复的文件名不包含order-only依赖</p>
<p><strong>$|</strong>所有order-only依赖文件名</p>
<p><strong>$*</strong>(简单理解)目标文件名的主干部分(即不包括后缀名)</p>
<p><strong>$%</strong>:如果目标不是归档文件,则为空;如果目标是归档文件成员,则为对应的成员文件名</p>
<p>&nbsp;</p>
<p>以下变量对应上述变量D为对应变量所在的目录结尾不带/F为对应变量除去目录部分的文件名</p>
<p><strong>$(@D)</strong></p>
<p><strong>$(@F)</strong></p>
<p><strong>$(*D)</strong></p>
<p><strong>$(*F)</strong></p>
<p><strong>$(%D)</strong></p>
<p><strong>$(%F)</strong></p>
<p><strong>$(&lt;D)</strong></p>
<p><strong>$(&lt;F)</strong></p>
<p><strong>$(^D)</strong></p>
<p><strong>$(^F)</strong></p>
<p><strong>$(+D)</strong></p>
<p><strong>$(+F)</strong></p>
<p><strong>$(?D)</strong></p>
<p><strong>$(?F)</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="绑定目标的变量">绑定目标的变量</h3>
<p>Makefile中的变量一般是全局变量。也就是说定义之后在Makefile的任意位置都可以使用。但也可以将变量指定在某个目标的范围内这样这个变量就只能在这个目标对应的规则里面保用</p>
<p>语法</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">target …</span> <span class="token punctuation">:</span> variable-assignment
<span class="token target symbol">target …</span> <span class="token punctuation">:</span> prerequisites
recipes
</code></pre>
<p></p>
<pre><code class="fenced-code-block language-makefile">var1 <span class="token operator">=</span> Global Var
<span class="token target symbol">first</span><span class="token punctuation">:</span> all t2
<span class="token target symbol">all</span><span class="token punctuation">:</span> var2 <span class="token operator">=</span> Target All Var
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>var2<span class="token punctuation">)</span>
<span class="token target symbol">t2</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>var2<span class="token punctuation">)</span></code></pre>
<p>这种定义变量的方式,目标也可以使用模式匹配,这样所有能匹配上的目标范围内都可以使用这些变量</p>
<pre><code class="fenced-code-block language-makefile">var1 <span class="token operator">=</span> Global Var
<span class="token target symbol">first</span><span class="token punctuation">:</span> all.v t2.v t3
<span class="token target symbol">%.v</span><span class="token punctuation">:</span> var2 <span class="token operator">=</span> Target %.v Var
<span class="token target symbol">all.v</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var2<span class="token punctuation">)</span>
<span class="token target symbol">t2.v</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var2<span class="token punctuation">)</span>
<span class="token target symbol">t3</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$@</span> -- <span class="token variable">$</span><span class="token punctuation">(</span>var2<span class="token punctuation">)</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 class="atx" id="二次展开">二次展开</h3>
<p>前面说过依赖中的变量都是在Makefile读取阶段立即展开的。如果想让依赖的的变量延迟展开可以使用.SECONDEXPANSION:,添加之后,在依赖中使用变量时用<code>$$</code>,可以让变量在第二阶段进行二次展开,从而达到延迟展开的效果。</p>
<pre><code class="fenced-code-block language-makefile">VAR1 <span class="token operator">=</span> main.cpp
<span class="token builtin-target builtin">.SECONDEXPANSION</span><span class="token punctuation">:</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span> <span class="token variable">$$</span><span class="token punctuation">(</span>VAR1<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$^</span>
VAR1 <span class="token operator">=</span> hello.cpp</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="自动推导与隐式规则">自动推导与隐式规则</h1>
<p>Makefile中有一些生成目标文件的规则使用频率非常高比如由.c或.cpp文件编译成.o文件这样的规则在make中可以自动推导所以可以不用明确写出来这样的规则称为隐式规则。</p>
<h2 class="atx" id="一些make预定义的规则">一些make预定义的规则</h2>
<h3 class="atx" id="c语言编译">C语言编译</h3>
<p>从.c到.o</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>CC<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>CPPFLAGS<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>CFLAGS<span class="token punctuation">)</span> -c</code></pre>
<h3 class="atx" id="c编译">C++编译</h3>
<p>从.cc .cpp .C到.o</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>CXX<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>CPPFLAGS<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>CXXFLAGS<span class="token punctuation">)</span> -c</code></pre>
<h3 class="atx" id="链接">链接</h3>
<p>由.o文件链接到可执行文件</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>CC<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>LDFLAGS<span class="token punctuation">)</span> *.o <span class="token variable">$</span><span class="token punctuation">(</span>LOADLIBES<span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span>LDLIBS<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="隐式规则中常用一些变量">隐式规则中常用一些变量</h2>
<p>这些变量都有默认值,也可以自行修改</p>
<h3 class="atx" id="cc">CC</h3>
<p>编译C语言的程序默认为 <code>cc</code></p>
<h3 class="atx" id="cxx">CXX</h3>
<p>编译C++的程序,默认为 <code>g++</code></p>
<h3 class="atx" id="ar">AR</h3>
<p>归档程序,默认为 <code>ar</code></p>
<h3 class="atx" id="cpp">CPP</h3>
<p>C语言预处理程序默认为 <code>$(CC) -E</code></p>
<h3 class="atx" id="rm">RM</h3>
<p>删除文件的程序,默认为<code>rm -f</code></p>
<h3 class="atx" id="cflags">CFLAGS</h3>
<p>传递给C编译器的一些选项如-O2 -Iinclude</p>
<h3 class="atx" id="cxxflags">CXXFLAGS</h3>
<p>传递给C++编译器的一些选项,如-std=c++ 11 -fexec-charset=GBK </p>
<h3 class="atx" id="cppflags">CPPFLAGS</h3>
<p>C语言预处理的一些选项</p>
<h3 class="atx" id="ldflags">LDFLAGS</h3>
<p>链接选项,如-L.</p>
<h3 class="atx" id="ldlibs">LDLIBS</h3>
<p>链接需要用到的库,如-lkernel32 -luser32 -lgdi32</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="多目标与多规则">多目标与多规则</h1>
<p>显式规则中一条规则可以有多个目标,多个目标可以是相互独立的目标,也可以是组合目标,用写法来区分</p>
<h2 class="atx" id="独立多目标">独立多目标</h2>
<p>相互独立的多个目标与依赖之间直接用<code>:</code>,常用这种方式的有以下两种情况</p>
<ol>
<li><p>只需要写目标和依赖,不需要写方法的时候</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o input.o scene.o</span> <span class="token punctuation">:</span> common.h</code></pre>
<p>这种写法等价于</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o</span> <span class="token punctuation">:</span> common.h
<span class="token target symbol">input.o</span> <span class="token punctuation">:</span> common.h
<span class="token target symbol">scene.o</span> <span class="token punctuation">:</span> common.h</code></pre>
</li>
<li><p>生成(更新)目标的方法写法一样的只是依赖与目标不一样时。之前写的Makfile中有如下代码</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o</span><span class="token punctuation">:</span> block.cpp common.h block.h color.h
g++ -c block.cpp
<span class="token target symbol">command.o</span><span class="token punctuation">:</span> command.cpp command.h scene.h
g++ -c command.cpp
<span class="token target symbol">input.o</span><span class="token punctuation">:</span> input.cpp common.h utility.inl
g++ -c input.cpp
<span class="token target symbol">main.o</span><span class="token punctuation">:</span> main.cpp scene.h input.h test.h
g++ -c main.cpp
<span class="token target symbol">scene.o</span><span class="token punctuation">:</span> scene.cpp common.h scene.h utility.inl
g++ -c scene.cpp
<span class="token target symbol">test.o</span><span class="token punctuation">:</span> test.cpp test.h
g++ -c test.cpp</code></pre>
<p>所有.o文件的生成都用的同一方法</p>
<pre><code class="fenced-code-block language-makefile">g++ -c &lt;文件名&gt;</code></pre>
<p>如果不考虑依赖源文件进行更新时,可以进行简写如下:</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o command.o input.o main.o scene.o test.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
<span class="token target symbol"> g++ -c <span class="token variable">$</span>(@</span><span class="token punctuation">:</span>%.o<span class="token operator">=</span>%.cpp<span class="token punctuation">)</span></code></pre>
<p>这种写法实际上等价于</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span>
<span class="token target symbol">command.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span>
<span class="token target symbol">input.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span>
<span class="token target symbol">main.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span>
<span class="token target symbol">scene.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span>
<span class="token target symbol">test.o</span> <span class="token punctuation">:</span> common.h block.h command.h ...
g++ -c <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$@</span><span class="token punctuation">)</span></code></pre>
<p>其中,<span class="katex"><span class="katex-mathml"></span><span aria-hidden="true" class="katex-html"><span class="base"><span style="height:0.6944em;" class="strut"></span><span class="mord">@</span><span class="mord cjk_fallback">表示的是目标名称。</span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">b</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord cjk_fallback">是一个字符串替换函数,</span></span></span></span>(subst .o,.cpp,$@)表示将目标名称中的.o替换为.cpp。</p>
<p>这样的简写可以减少内容的书写量,但是不利于将每个目标与依赖分别对应。</p>
</li>
</ol>
<p>独立多目标虽然写在一起,但是每个目标都是单独调用一次方法来更新的。和分开写效果一样。</p>
<h2 class="atx" id="组合多目标">组合多目标</h2>
<p>多目标与依赖之前用<code>&amp;:</code>,这样的多个目标称为组合目标。与独立多目标的区别在于,独立多目标每个目标的更新需要单独调用一次更新方法。而组合多目标调用一次方法将更新所有目标</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o input.o scene.o &amp;</span><span class="token punctuation">:</span> block.cpp input.cpp scene.cpp common.h
g++ -c block.cpp
g++ -c input.cpp
g++ -c scene.cpp</code></pre>
<p>所有目标的更新方法都写到其中,每次更新只会调用一次。</p>
<h2 class="atx" id="同一目标多条规则">同一目标多条规则</h2>
<p>同一目标可以对应多条规则。同一目标的所有规则中的依赖会被合并。但如果同一目标对应的多条规则都写了更新方法,则会使用最新的一条更新方法,并且会输出警告信息。</p>
<p>同一目标多规则通常用来给多个目标添加依赖而不用改动已写好的部分。</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">input.o</span><span class="token punctuation">:</span> input.cpp utility.inl
g++ -c input.cpp
<span class="token target symbol">main.o</span><span class="token punctuation">:</span> main.cpp scene.h input.h test.h
g++ -c main.cpp
<span class="token target symbol">scene.o</span><span class="token punctuation">:</span> scene.cpp scene.h utility.inl
g++ -c scene.cpp
<span class="token target symbol">input.o main.o scene.o</span> <span class="token punctuation">:</span> common.h</code></pre>
<p>同时给三个目标添加了一个依赖common.h但是不用修改上面已写好的部分。</p>
<h1 class="atx" id="静态模式">静态模式</h1>
<p>独立多目标可以简化Makefile的书写但是不利于将各个目标的依赖分开让目标文件根据各自的依赖进行更新。静态模式可以在一定程度上改进依赖分开问题。</p>
<p>静态模式就是用<code>%</code>进行文件匹配来推导出对应的依赖。</p>
<p><strong>语法</strong></p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">targets …</span><span class="token punctuation">:</span> target-pattern<span class="token punctuation">(</span>目标模式<span class="token punctuation">)</span><span class="token punctuation">:</span> prereq-patterns<span class="token punctuation">(</span>依赖模式<span class="token punctuation">)</span>
recipe
</code></pre>
<p>先看一个例子</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o</span> <span class="token punctuation">:</span> %.o <span class="token punctuation">:</span> %.cpp %.h
g++ -c <span class="token variable">$&lt;</span></code></pre>
<p>block.o为目标%.o为目标模式%.cpp%.h为依赖模式对于这一条规则%.o代表的是目标文件block.o所以这里的%匹配的是block因此%.cpp表示block.cpp%.h代表block.h所以block.o : %.o : %.cpp %.h表示的意思同下面这种写法</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o</span> <span class="token punctuation">:</span> block.cpp block.h</code></pre>
<p>自动推导出block.o依赖block.cpp和block.h。</p>
<p>另外,$&lt;表示目标的第一个依赖,在这条规则中,$&lt;表示block.cpp</p>
<p>对应的Makefile可以做如下改进</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">block.o command.o input.o scene.o test.o</span><span class="token punctuation">:</span> %.o <span class="token punctuation">:</span> %.cpp %.h
g++ -c <span class="token variable">$&lt;</span>
<span class="token target symbol">main.o</span><span class="token punctuation">:</span> main.cpp scene.h input.h test.h
g++ -c main.cpp</code></pre>
<p>用这种方式可以在简写的同时一定程度上解决各个目标对应的依赖问题。</p>
<p>(不属于静态模式的内容,隐式规则的内容)利用模式匹配可以直接将所有.cpp到.o文件的编译简写为如下</p>
<pre><code class="fenced-code-block language-makefile"><span class="token target symbol">%.o</span> <span class="token punctuation">:</span> %.cpp %.h
g++ -c <span class="token variable">$&lt;</span></code></pre>
<h1 class="atx" id="条件判断">条件判断</h1>
<p>使用条件指令可以让make执行或略过Makefile文件中的一些部分。</p>
<p><strong>ifdef</strong> 判断一个变量是已否定义</p>
<pre><code class="fenced-code-block language-makefile">OS <span class="token operator">=</span> Linux
<span class="token keyword">ifdef</span> Win
OS <span class="token operator">=</span> Windows
<span class="token keyword">endif</span>
OS <span class="token operator">=</span> Linux
<span class="token keyword">ifdef</span> Win
OS <span class="token operator">=</span> Windows
<span class="token keyword">else</span> <span class="token keyword">ifdef</span> Mac
OS<span class="token operator">=</span> MacOS
<span class="token keyword">endif</span>
<span class="token keyword">ifdef</span> Win
OS <span class="token operator">=</span> Windows
<span class="token keyword">else</span> <span class="token keyword">ifdef</span> Mac
OS<span class="token operator">=</span> MacOS
<span class="token keyword">else</span>
OS <span class="token operator">=</span> Linux
<span class="token keyword">endif</span></code></pre>
<p><strong>ifndef</strong> 判断一个变量是否没被定义</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">ifndef</span> FLAGS
FLAGS <span class="token operator">=</span> -finput-charset<span class="token operator">=</span>utf-8
<span class="token keyword">endif</span></code></pre>
<p><strong>ifeq</strong> 判断两个值是否相等</p>
<pre><code class="fenced-code-block language-makefile">version <span class="token operator">=</span> 3.0
<span class="token keyword">ifeq</span> <span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span>version<span class="token punctuation">)</span>,1.0<span class="token punctuation">)</span> <span class="token comment"># ifeq后一定要一个空格</span>
msg <span class="token operator">:=</span> 版本太旧了,请更新版本
<span class="token keyword">else</span> <span class="token keyword">ifeq</span> <span class="token punctuation">(</span><span class="token variable">$</span><span class="token punctuation">(</span>version<span class="token punctuation">)</span>, 3.0<span class="token punctuation">)</span>
msg <span class="token operator">:=</span> 版本太新了,也不行
<span class="token keyword">else</span>
msg <span class="token operator">:=</span> 版本可以用
<span class="token keyword">endif</span>
<span class="token comment"># 另外的写法</span>
msg <span class="token operator">=</span> Other
<span class="token keyword">ifeq</span> <span class="token string">"$(OS)"</span> <span class="token string">"Windows_NT"</span>
msg <span class="token operator">=</span> This is a Windows Platform
<span class="token keyword">endif</span>
<span class="token keyword">ifeq</span> <span class="token string">'$(OS)'</span> <span class="token string">'Windows_NT'</span>
<span class="token keyword">ifeq</span> <span class="token string">'$(OS)'</span> <span class="token string">"Windows_NT"</span></code></pre>
<p><strong>ifneq</strong> 判断两个值是否不等</p>
<p>用法及参数同ifeq只是判断结果相反</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="文本处理函数">文本处理函数</h1>
<p>C语言中函数调用方法是function(arguments)但在Makefile中调用函数的写法不同</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>function arguments<span class="token punctuation">)</span><span class="token variable">$</span><span class="token punctuation">{</span>function arguments<span class="token punctuation">}</span>
<span class="token variable">$</span><span class="token punctuation">(</span>function arg1,<span class="token variable">$</span><span class="token punctuation">(</span>arg2<span class="token punctuation">)</span>,arg3 ...<span class="token punctuation">)</span> <span class="token comment"># 参数之间不要有空格</span></code></pre>
<h2 class="atx" id="字符替换与分析">字符替换与分析</h2>
<h4 class="atx" id="subst"><strong>subst</strong></h4>
<p>文本替换函数,返回替换后的文本</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> target,replacement,text<span class="token punctuation">)</span>
--- 用relacement替换text中的target
--- target 需要替换的内容
--- replacement 替换为的内容
--- text 需要处理的内容,可以是任意字符串
objs <span class="token operator">=</span> main.o hello.o
srcs <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .o,.cpp,<span class="token variable">$</span><span class="token punctuation">(</span>objs<span class="token punctuation">)</span><span class="token punctuation">)</span>
headers <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> .cpp,.h,<span class="token variable">$</span><span class="token punctuation">(</span>srcs<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>srcs<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>headers<span class="token punctuation">)</span></code></pre>
<p><strong>patsubst</strong></p>
<p>模式替换, 返回替换后的文本</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">patsubst</span> pattern,replacement,text<span class="token punctuation">)</span>
--- pattern 需要替换的模式
--- replacement 需要替换为
--- text 待处理内容,各项内容需要用空格隔开
objs <span class="token operator">=</span> main.ohello.o
srcs <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> %.o,%.cpp,<span class="token variable">$</span><span class="token punctuation">(</span>objs<span class="token punctuation">)</span><span class="token punctuation">)</span>
headers <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> %.cpp,%.h,<span class="token variable">$</span><span class="token punctuation">(</span>srcs<span class="token punctuation">)</span><span class="token punctuation">)</span> </code></pre>
<h4 class="atx" id="strip"><strong>strip</strong></h4>
<p>去除字符串头部和尾部的空格,中间如果连续有多个空格,则用一个空格替换,返回去除空格后的文本</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">strip</span> string<span class="token punctuation">)</span>
--- string 需要去除空格的字符串
files <span class="token operator">=</span> aa hello.cpp main.cpp test.cpp
files <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">subst</span> aa, ,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span>
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">strip</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="findstring">findstring</h4>
<p>查找字符串,如果找到了,则返回对应的字符串,如果没找到,则反回空串</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">findstring</span> find,string<span class="token punctuation">)</span>
--- find 需要查找的字符串
--- string 用来查找的内容
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp
find <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">findstring</span> hel,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span>
find <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">findstring</span> HEL,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="filter">filter</h4>
<p>从文本中筛选出符合模式的内容并返回</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">filter</span> pattern…,text<span class="token punctuation">)</span>
--- pattern 模式,可以有多个,用空格隔开
--- text 用来筛选的文本,多项内容需要用空格隔开,否则只会当一项来处理
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">filter</span> %.o %.h,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="filter-out">filter-out</h4>
<p>与filter相反过滤掉符合模式的返回剩下的内容</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">filter-out</span> pattern…,text<span class="token punctuation">)</span>
--- pattern 模式,可以有多个,用空格隔开
--- text 用来筛选的文本,多项内容需要用空格隔开,否则只会当一项来处理
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">filter-out</span> %.o %.cpp,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="sort">sort</h4>
<p>将文本内的各项按字典顺序排列,并且移除重复项</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">sort</span> list<span class="token punctuation">)</span>
--- list 需要排序内容
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h main.cpp hello.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">sort</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="word">word</h4>
<p>用于返回文本中第n个单词</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">word</span> n,text<span class="token punctuation">)</span>
--- n 第n个单词从1开始如果n大于总单词数则返回空串
--- text 待处理文本
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h main.cpp hello.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">word</span> 3,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="wordlist">wordlist</h4>
<p>用于返回文本指定范围内的单词列表</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wordlist</span> start,end,text<span class="token punctuation">)</span>
--- start 起始位置,如果大于单词总数,则返回空串
--- end 结束位置如果大于单词总数则返回起始位置之后全部如果start &gt; end什么都不返回
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h main.cpp hello.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wordlist</span> 3,6,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="words">words</h4>
<p>返回文本中单词数</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">words</span> text<span class="token punctuation">)</span>
--- text 需要处理的文本
files <span class="token operator">=</span> hello.cpp main.cpp test.cpp main.o hello.o hello.h main.cpp hello.cpp
nums <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">words</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="firstword">firstword</h4>
<p>返回第一个单词</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">firstword</span> text<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="lastword">lastword</h4>
<p>返回最后一个单词</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">lastword</span> text<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="文件名处理函数">文件名处理函数</h2>
<h4 class="atx">dir</h4>
<p>返回文件目录</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">dir</span> files<span class="token punctuation">)</span>
--- files 需要返回目录的文件名,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">dir</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="notdir">notdir</h4>
<p>返回除目录部分的文件名</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">notdir</span> files<span class="token punctuation">)</span>
--- files 需要返回文件列表,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">notdir</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="suffix">suffix</h4>
<p>返回文件后缀名,如果没有后缀返回空</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">suffix</span> files<span class="token punctuation">)</span>
--- files 需要返回后缀的文件名,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">suffix</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="basename">basename</h4>
<p>返回文件名除后缀的部分</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">basename</span> files<span class="token punctuation">)</span>
--- files 需要返回的文件名,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">basename</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="addsuffix">addsuffix</h4>
<p>给文件名添加后缀</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">addsuffix</span> suffix,files<span class="token punctuation">)</span>
--- suffix 需要添加的后缀
--- files 需要添加后缀的文件名,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">addsuffix</span> .exe,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="addprefix">addprefix</h4>
<p>给文件名添加前缀</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>addprefix prefix,files<span class="token punctuation">)</span>
--- prefix 需要添加的前缀
--- files 需要添加前缀的文件名,可以有多个,用空格隔开
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>addprefix make/,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="join">join</h4>
<p>将两个列表中的内容一对一连接,如果两个列表内容数量不相等,则多出来的部分原样返回</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">join</span> list1,list2<span class="token punctuation">)</span>
--- list1 第一个列表
--- list2 需要连接的第二个列表
f1 <span class="token operator">=</span> hello main test
f2 <span class="token operator">=</span> .cpp .hpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">join</span> <span class="token variable">$</span><span class="token punctuation">(</span>f1<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f2<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="wildcard">wildcard</h4>
<p>返回符合通配符的文件列表</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> pattern<span class="token punctuation">)</span>
--- pattern 通配符
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> *.cpp<span class="token punctuation">)</span>
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> *<span class="token punctuation">)</span>
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> src/*.cpp<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="realpath">realpath</h4>
<p>返回文件的绝对路径</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">realpath</span> files<span class="token punctuation">)</span>
--- files 需要返回绝对路径的文件,可以有多个,用空格隔开
f3 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> src/*<span class="token punctuation">)</span>
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">realpath</span> <span class="token variable">$</span><span class="token punctuation">(</span>f3<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="abspath">abspath</h4>
<p>返回绝对路径用法同realpath如果一个文件名不存在realpath不会返回内容abspath则会返回一个当前文件夹一下的绝对路径</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">abspath</span> files<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="条件函数">条件函数</h2>
<h4 class="atx" id="if">if</h4>
<p>条伯判断,如果条件展开不是空串,则反回真的部分,否则返回假的部分</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">if</span> condition,then-part[,<span class="token keyword">else</span>-part]<span class="token punctuation">)</span>
--- condition 条件部分
--- then-part 条件为真时执行的部分
--- <span class="token keyword">else</span>-part 条件为假时执行的部分,如果省略则为假时返回空串
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">if</span> <span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span>,有文件,没有文件<span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="or">or</h4>
<p>返回条件中第一个不为空的部分</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">or</span> condition1[,condition2[,condition3…]]<span class="token punctuation">)</span>
f1 <span class="token operator">=</span>
f2 <span class="token operator">=</span>
f3 <span class="token operator">=</span> hello.cpp
f4 <span class="token operator">=</span> main.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">or</span> <span class="token variable">$</span><span class="token punctuation">(</span>f1<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f2<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f3<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f4<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="and">and</h4>
<p>如果条件中有一个为空串,则返回空,如果全都不为空,则返回最后一个条件</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">and</span> condition1[,condition2[,condition3…]]<span class="token punctuation">)</span>
f1 <span class="token operator">=</span> 12
f2 <span class="token operator">=</span> 34
f3 <span class="token operator">=</span> hello.cpp
f4 <span class="token operator">=</span> main.cpp
files2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">and</span> <span class="token variable">$</span><span class="token punctuation">(</span>f1<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f2<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f3<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>f4<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h4 class="atx" id="intcmp">intcmp</h4>
<p>比较两个整数大小并返回对应操作结果GNU make 4.4以上版本)</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>intcmp lhs,rhs[,lt-part[,eq-part[,gt-part]]]<span class="token punctuation">)</span>
--- lhs 第一个数
--- rhs 第二个数
--- lt-part lhs &lt; rhs时执行
--- eq-part lhs <span class="token operator">=</span> rhs时执行
--- gt-part lhs &gt; rhs时执行
--- 如果只提供前两个参数则lhs <span class="token operator">=</span><span class="token operator">=</span> rhs时返回数值否则返回空串
参数为lhs,rhs,lt-part时当lhs &lt; rhs时返回lt-part结果否则返回空
参数为lhs,rhs,lt-part,eq-partlhs &lt; rhs返回lt-part结果否则都返回eq-part结果
参数全时lhs &lt; rhs返回lt-partlhs <span class="token operator">=</span><span class="token operator">=</span> rhs返回eq-part, lhs &gt; rhs返回gt-part
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span>intcmp 2,2,-1,0,1<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="file">file</h2>
<p>读写文件</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">file</span> op filename[,text]<span class="token punctuation">)</span>
--- op 操作
&gt; 覆盖
&gt;&gt; 追加
&lt;
--- filename 需要操作的文件名
--- text 写入的文本内容,读取是不需要这个参数
files <span class="token operator">=</span> src/hello.cpp main.cpp hello.o hello.hpp hello
write <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">file</span> &gt; makewrite.txt,<span class="token variable">$</span><span class="token punctuation">(</span>files<span class="token punctuation">)</span><span class="token punctuation">)</span>
read <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">file</span> &lt; makewrite.txt<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="foreach">foreach</h2>
<p>对一列用空格隔开的字符序列中每一项进行处理,并返回处理后的列表</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">foreach</span> each,list,process<span class="token punctuation">)</span>
--- each list中的每一项
--- list 需要处理的字符串序列,用空格隔开
--- process 需要对每一项进行的处理
list <span class="token operator">=</span> 1 2 3 4 5
result <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">foreach</span> each,<span class="token variable">$</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>addprefix cpp,<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">addsuffix</span> .cpp,<span class="token variable">$</span><span class="token punctuation">(</span>each<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<p>作用类似C/C++中的循环</p>
<pre><code class="fenced-code-block language-c++">int list[5] = {1, 2, 3, 4, 5};
int result[5];
int each;
for(int i = 0; i &lt; 5; i++)
{
each = list[i];
result[i] = process(each);
}
// 此时result即为返回结果</code></pre>
<h2 class="atx" id="call">call</h2>
<p>将一些复杂的表达式写成一个变量用call可以像调用函数一样进行调用。类似于编程语言中的自定义函数。在函数中可以用$(n)来访问第n个参数</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">call</span> funcname,param1,param2,…<span class="token punctuation">)</span>
--- funcname 自定义函数(变量名)
--- 参数至少一个,可以有多个,用逗号隔开
dirof <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">dir</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">realpath</span> <span class="token variable">$</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">dir</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">realpath</span> <span class="token variable">$</span><span class="token punctuation">(</span>2<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
result <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">call</span> dirof,main.cpp,src/hello.cpp<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="value">value</h2>
<p>对于不是立即展开的变量,可以查看变量的原始定义;对于立即展开的变量,直接返回变量值</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">value</span> variable<span class="token punctuation">)</span>
var <span class="token operator">=</span> value function test
var2 <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>var<span class="token punctuation">)</span>
var3 <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>var<span class="token punctuation">)</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">value</span> var2<span class="token punctuation">)</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">value</span> var3<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id=""></h2>
<p>查看一个变量定义来源</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> variable<span class="token punctuation">)</span>
var2 <span class="token operator">=</span> origin function
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> var1<span class="token punctuation">)</span> <span class="token comment"># undefined 未定义</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> CC<span class="token punctuation">)</span> <span class="token comment"># default 默认变量</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> JAVA_HOME<span class="token punctuation">)</span> <span class="token comment"># environment 环境变量</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> var2<span class="token punctuation">)</span> <span class="token comment"># file 在Makefile文件中定义的变量</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">origin</span> <span class="token operator">@</span><span class="token punctuation">)</span> <span class="token comment"># automatic 自动变量</span></code></pre>
<h2 class="atx" id="flavor">flavor</h2>
<p>查看一个变量的赋值方式</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">flavor</span> variable<span class="token punctuation">)</span>
var2 <span class="token operator">=</span> flavor function
var3 <span class="token operator">:=</span> flavor funciton
<span class="token target symbol">all</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">flavor</span> var1<span class="token punctuation">)</span> <span class="token comment"># undefined 未定义</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">flavor</span> var2<span class="token punctuation">)</span> <span class="token comment"># recursive 递归展开赋值</span>
<span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">flavor</span> var3<span class="token punctuation">)</span> <span class="token comment"># simple 简单赋值</span></code></pre>
<h2 class="atx" id="eval">eval</h2>
<p>可以将一段文本生成Makefile的内容</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">eval</span> text<span class="token punctuation">)</span>
<span class="token keyword">define</span> eval_target <span class="token operator">=</span>
<span class="token target symbol">eval</span><span class="token punctuation">:</span>
<span class="token operator">@</span>echo Target Eval Test
<span class="token keyword">endef</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">eval</span> <span class="token variable">$</span><span class="token punctuation">(</span>eval_target<span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<p>以上运行make时将会执行eval目标</p>
<h2 class="atx" id="shell">shell</h2>
<p>用于执行Shell命令</p>
<pre><code class="fenced-code-block language-makefile">files <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">shell</span> ls *.cpp<span class="token punctuation">)</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">shell</span> echo This is from shell function<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="let">let</h2>
<p>将一个字符串序列中的项拆开放入多个变量中并对各个变量进行操作GNU make 4.4以上版本)</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>let var1 [var2 ...],[list],proc<span class="token punctuation">)</span>
--- var 变量,可以有多个,用空格隔开
--- list 待处理字符串,各项之间空格隔开
--- proc 对变量进行的操作结果为let的返回值
将list中的值依次一项一项放到var中如果var的个数多于list项数那多出来的var是空串。如果
var的个数小于list项数则先依次把前而的项放入var中剩下的list所有项都放入最后一个var中
list <span class="token operator">=</span> a b c d
letfirst <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>let first second rest,<span class="token variable">$</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>first<span class="token punctuation">)</span><span class="token punctuation">)</span>
letrest <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>let first second rest,<span class="token variable">$</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span>rest<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment"># 结合call可以对所有项进行递归处理</span>
reverse <span class="token operator">=</span> <span class="token variable">$</span><span class="token punctuation">(</span>let first rest,<span class="token variable">$</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">if</span> <span class="token variable">$</span><span class="token punctuation">(</span>rest<span class="token punctuation">)</span>,<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">call</span> reverse,<span class="token variable">$</span><span class="token punctuation">(</span>rest<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token variable">$</span><span class="token punctuation">(</span>first<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token target symbol">all</span><span class="token punctuation">:</span> <span class="token punctuation">;</span> <span class="token operator">@</span>echo <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">call</span> reverse,d c b a<span class="token punctuation">)</span></code></pre>
<h2 class="atx" id="信息提示函数">信息提示函数</h2>
<h4 class="atx" id="error">error</h4>
<p>提示错误信息并终止make执行</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">error</span> text<span class="token punctuation">)</span>
--- text 提示信息
EXIT_STATUS <span class="token operator">=</span> -1
<span class="token keyword">ifneq</span> <span class="token punctuation">(</span>0, <span class="token variable">$</span><span class="token punctuation">(</span>EXIT_STATUS<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">error</span> An error occured! make stopped!<span class="token punctuation">)</span>
<span class="token keyword">endif</span></code></pre>
<h4 class="atx" id="warning">warning</h4>
<p>提示警告信息make不会终止</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">warning</span> text<span class="token punctuation">)</span>
<span class="token keyword">ifneq</span> <span class="token punctuation">(</span>0, <span class="token variable">$</span><span class="token punctuation">(</span>EXIT_STATUS<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">warning</span> This is a warning message<span class="token punctuation">)</span>
<span class="token keyword">endif</span></code></pre>
<h4 class="atx" id="info">info</h4>
<p>输出一些信息</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">info</span> text…<span class="token punctuation">)</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">info</span> 编译开始.......<span class="token punctuation">)</span>
<span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">info</span> 编译结束<span class="token punctuation">)</span></code></pre>
<h1 class="atx" id="同一项目中有多个makefile文件">同一项目中有多个Makefile文件</h1>
<h2 class="atx" id="包含其他makefile文件">包含其他makefile文件</h2>
<p>使用<code>include</code>指令可以读入其他makefile文件的内容效果就如同在include的位置用对应的文件内容替换一样。</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">include</span> mkf1 mkf2 <span class="token comment"># 可以引入多个文件,用空格隔开</span>
<span class="token keyword">include</span> *.mk <span class="token comment"># 可以用通配符,表示引入所有以.mk结尾的文件</span></code></pre>
<p>如果找不到对应文件,则会报错,如果要忽略错误,可以在<code>include</code>前加<code>-</code></p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">-include</span> mkf1 mkf2</code></pre>
<h4 class="atx" id="应用实例:自动生成依赖">应用实例:自动生成依赖</h4>
<pre><code class="fenced-code-block language-makefile">objs <span class="token operator">=</span> block.o command.o input.o main.o scene.o test.o
<span class="token target symbol">sudoku</span><span class="token punctuation">:</span> <span class="token variable">$</span><span class="token punctuation">(</span>objs<span class="token punctuation">)</span>
g++ <span class="token variable">$</span><span class="token punctuation">(</span>objs<span class="token punctuation">)</span> -o sudoku
<span class="token target symbol">include <span class="token variable">$</span>(objs</span><span class="token punctuation">:</span>%.o<span class="token operator">=</span>%.d<span class="token punctuation">)</span>
<span class="token target symbol">%.d</span><span class="token punctuation">:</span> %.cpp
<span class="token operator">@</span>-rm <span class="token variable">$@</span>
<span class="token variable">$</span><span class="token punctuation">(</span>CXX<span class="token punctuation">)</span> -MM <span class="token variable">$&lt;</span> &gt; <span class="token variable">$@.temp</span>
<span class="token operator">@</span>sed <span class="token string">'s,\($*\)\.o[ :]*,\1.o $@ : ,g'</span> &lt; <span class="token variable">$@.temp</span> &gt; <span class="token variable">$@</span>
<span class="token operator">@</span>-rm <span class="token variable">$@.temp</span>
<span class="token target symbol">%.o</span> <span class="token punctuation">:</span> %.cpp
g++ -c <span class="token variable">$&lt;</span>
<span class="token operator">@</span>echo <span class="token variable">$^</span></code></pre>
<h2 class="atx" id="嵌套make">嵌套make</h2>
<p>如果将一个大项目分为许多小项目则可以使用嵌套递归使用make。具体做法为写一个总的Makefile然后在每个子项目中都写一个Makefile在总Makefile中进行调用。</p>
<p>例如可以把sudoku项目中除main.cpptest.cpp外的其他cpp存为一个子项目编译为一个库文件main.cpp test.cpp为另一个子项目编译为.o然后链接库文件成可执行文件</p>
<p>库文件Makefile</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">vpath</span> %.h ../<span class="token keyword">include</span>
CXXFLAGS <span class="token operator">+=</span> -I../<span class="token keyword">include</span> -fexec-charset<span class="token operator">=</span>GBK -finput-charset<span class="token operator">=</span>UTF-8
cpps <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span><span class="token function">wildcard</span> *.cpp<span class="token punctuation">)</span>
objs <span class="token operator">:=</span> <span class="token variable">$</span><span class="token punctuation">(</span>cpps<span class="token punctuation">:</span>%.cpp<span class="token operator">=</span>%.o<span class="token punctuation">)</span>
<span class="token target symbol">libsudoku.a</span><span class="token punctuation">:</span> <span class="token variable">$</span><span class="token punctuation">(</span>objs<span class="token punctuation">)</span>
ar rcs <span class="token variable">$@</span> <span class="token variable">$^</span>
<span class="token target symbol"><span class="token variable">$</span>(objs)</span><span class="token punctuation">:</span> %.o <span class="token punctuation">:</span> %.cpp %.h</code></pre>
<p>main.cpp test.cpp的Makefile</p>
<pre><code class="fenced-code-block language-makefile">CXXFLAGS <span class="token operator">+=</span> -I../<span class="token keyword">include</span> -fexec-charset<span class="token operator">=</span>GBK -finput-charset<span class="token operator">=</span>UTF-8
<span class="token keyword">vpath</span> %.h ../<span class="token keyword">include</span>
<span class="token keyword">vpath</span> %.a ../lib
<span class="token target symbol">../sudoku</span><span class="token punctuation">:</span> main.o test.o -lsudoku
<span class="token variable">$</span><span class="token punctuation">(</span>CXX<span class="token punctuation">)</span> -o <span class="token variable">$@</span> <span class="token variable">$^</span></code></pre>
<p>总的Makefile</p>
<pre><code class="fenced-code-block language-makefile"><span class="token builtin-target builtin">.PHONY</span><span class="token punctuation">:</span> all clean
<span class="token target symbol">all</span><span class="token punctuation">:</span> subsrc
<span class="token target symbol">subsrc</span><span class="token punctuation">:</span> sublib
<span class="token variable">$</span><span class="token punctuation">(</span>MAKE<span class="token punctuation">)</span> -C src
<span class="token target symbol">sublib</span><span class="token punctuation">:</span>
<span class="token variable">$</span><span class="token punctuation">(</span>MAKE<span class="token punctuation">)</span> -C lib
<span class="token target symbol">clean</span><span class="token punctuation">:</span>
-rm *.exe src/*.o lib/*.o lib/*.a </code></pre>
<p>其中</p>
<pre><code class="fenced-code-block language-makefile"><span class="token variable">$</span><span class="token punctuation">(</span>MAKE<span class="token punctuation">)</span> -C subdir</code></pre>
<p>这一指令会自动进入subdir文件夹然后执行make。</p>
<p>可以通过<code>export</code>指令向子项目的make传递变量。</p>
<pre><code class="fenced-code-block language-makefile"><span class="token keyword">export</span> var <span class="token comment"># 传递var</span>
<span class="token keyword">export</span> <span class="token comment"># 传递所有变量</span>
<span class="token keyword">unexport</span> <span class="token comment"># 取消传递</span></code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1 class="atx" id="后续学习过程">后续学习过程</h1>
<p>读一些开源项目的Makefile</p>
<p><strong>redis</strong>:https://github.com/redis/redis</p>
<p><strong>ffmpeg</strong>:https://github.com/FFmpeg/FFmpeg</p>
<p><strong>aubio</strong>:https://github.com/aubio/aubio</p>
<p><strong>libav</strong>:https://github.com/libav/libav</p>
<p><strong>OpenH264</strong>:https://github.com/cisco/openh264</p>
<p><strong>TinyVM</strong>:https://github.com/jakogut/tinyvm</p>
<p><strong>TinyXML2</strong>:https://github.com/leethomason/tinyxml2</p>
</article>
</body>
</html>