.bashrc 中的自动编译别名

.bashrc 中的自动编译别名

如何在我的文件中创建别名,.bashrc以便我可以编译我的 C++ 程序而无需输入这个更长的命令:

g++ -o filename filename.cpp

此处的文件名是变量。

答案1

总结:改用make filename。考虑设置并导出CXXFLAGS警告。

如果您真的只对运行感兴趣g++ -o filename filename.cpp(没有启用编译器警告或以其他方式自定义编译器行为的选项),您可以只阅读下面的第一部分。有关使用 shell 别名和 shell 函数的替代方法的介绍,请参阅最后一节。

这个答案主要关注 C++,但其中大部分适用于 C。主要区别在于,make编译 C 源代码文件的标志传递来自CFLAGS而不是CXXFLAGS


您只需将基本名称传递给即可make

作为steeldriver 说,比 shell 函数或 shell 别名更好的解决方案是利用 的make隐式规则。运行命令的g++ -o filename filename.cpp效果与

make filename

...除非filename存在且不早于filename.cpp,在这种情况下make,不会再次编译它,而是报告make: 'filename' is up to date,这可能是您在这种情况下想要的。当您更改源代码文件时,它会变得比上次编译的可执行文件(如果有)更新,因此后续调用会make filename重新编译它。

正如steeldriver提到的,您只能使用一个以filename为基本名称的源代码文件来使用此方法。如果您有多种语言的源代码文件,例如filename.cfilename.cppfilename.m,那么make将根据其规则选择一个,并且它不一定是您想要的那个。

不使用 makefile运行make也仅在程序仅需要一个源代码文件时才有效。但这似乎是这种情况,也是刚开始学习用 C 或 C++ 编程时最常见的情况。

make实际运行以编译 C++ 源代码文件的命令实际上不是g++,而是c++。但是,c++在 Ubuntu(和大多数 GNU/Linux 系统)上,通常是一个解析为命令的符号链接g++,除非您故意更改它或仅安装了一些其他 C++ 编译器。

您应该启用警告,并且通常选择一种方言。

非常除了少数例外情况(例如检查编译器是否正常工作)外,您还应启用编译器警告。这会告诉您的编译器警告您可能包含错误的代码。默认情况下,大多数 C 和 C++ 编译器(包括流行的编译器 GCC 和 Clang(g++clang++命令))只会警告极少数情况。我将介绍如何在启用警告的情况下运行g++,然后我将展示如何make在运行 时启用警告make filename

至少,使用-Wall,由于历史原因,与其名称相反,它实际上并不启用全部警告。您也应该几乎总是使用-Wextra。您可以单独启用其他警告(man g++如果愿意,可以运行以查看所有警告),但这是一个好的开始,即使对于大型软件项目来说,这通常也是一个合理的选择。

我不知道您目前有多少 C++ 经验。经验丰富的程序员通常会使用警告并从中受益匪浅,但如果您是该语言的新手,您仍然不应该等待开始使用它们。这是因为它们可以为您省去很多麻烦,让您在程序中查找原本令人烦恼的错误,并且它们可以帮助您避免犯常见错误和养成坏习惯。

该命令g++ -o filename filename.cpp不要求任何警告,但会发出少量默认警告。相应的命令g++ -Wall -Wextra -o filename filename.cpp启用-Wall-Wextra。您可以将-Wall和放在-Wextra命令中的任何位置除了在和 之间-ofilename之前g++

如果你想尝试-Wall一次-Wextra,你可以make这样运行:

make CXXFLAGS='-Wall -Wextra' filename

filename.cpp请注意,如果源代码不比可执行文件新,即使您上次运行CXXFLAGS='-Wall -Wextra'时没有传递,它仍然不会重新编译。make

正如您所见,这相当麻烦;您的整个目标是用最少的输入来编译您的小程序。幸运的是,除了CXXFLAGS在命令行上接受对其变量的赋值外,make还尊重CXXFLAGS 环境变量如果有的话。因此你可以运行

export CXXFLAGS='-Wall -Wextra'

然后后续的运行make filename将通过-Wall会自动将和-Wextra给 C++ 编译器。但是,这不是永久性的;在其他 shell(不是从这个 shell 启动的)中,它不适用。

我将告诉你如何避免输入很快。但首先……

您应该选择一种方言,并考虑-pedantic更多警告。

您还应该说明g++您正在使用哪种 C++ 方言。例如,如果您使用的是没有 GNU 扩展的 C++17,请传递该-std=c++17选项。截至撰写本文时,C++17 是 C++ 的当前标准方言。如果您正在学习 C++,并且不确定想要哪种方言,您可以查阅您正在学习的任何材料或咨询您的导师(如果有)。如果这些都不适用,我建议使用当前标准,假设您的编译器支持它。告诉编译器-std=c++17不是强制您在程序中使用 C++ 的所有最新功能。如果您想要带有 GNU 扩展的 C++17,您可以使用-std=gnu++17;如果您不了解或不关心差异,那么这-std=c++17是合理的。

如果您不指定g++所需的方言,它将使用其默认方言,这在不同的 GCC 版本中有所不同。指定所需的方言有助于编译器在代码不正确(或可疑)且被视为以该特定方言编写时发出错误和警告。它还有助于编译器不是发出可能的错误和警告不是适合您使用的方言,因为如果没有它,编译器会假定您使用的是其默认方言。

如果您告诉g++您想要哪种方言,并且它是标准方言之一(例如,如果您使用-std=c++17,而不是),那么您可以通过传递标志-std=gnu++17来启用比原本显示的更多警告,关于不符合该方言的代码。其中一些警告实际上适用于所有或大多数标准方言。如果您希望这样的代码导致g++-pedantic错误发出 - 导致编译器故意失败并拒绝生成可执行文件,即使它可以 - 那么您可以使用-pedantic-errors

即使您没有指定方言,或者您指定的方言不是标准化的方言,您也可以传递这些标志,但您可能不想这样做,因为很难判断它们是否合理,而且您很可能最终会忽略其中的很多。您还可以关闭全部使用 可以将警告转换为错误-Werror,这是一种相当流行的做法,因为它使得无法忽略警告。但是,如果你刚刚开始,我建议不要这样做,即使警告应该不是除非在极不寻常的情况下,否则可以忽略。有时,让代码在编译时出现警告,然后试用,然后修复导致警告的问题,会很方便。

要包括-std=c++17-pedantic在您的CXXFLAGS

export CXXFLAGS='-std=c++17 -pedantic -Wall -Wextra'

如果你已经CXXFLAGS在 shell 中导出了,那么你可以export在后续赋值时省略它。但保留它也没有坏处。

您可以将export命令放在文件中,然后使用 来获取它.

您可以CXXFLAGS设置大多数环境变量的方式,例如PATH,将export其命令放入 中~/.profile。但我建议不要这样做,因为您可能会使用make其他作者编写的软件来构建软件,而您通常首选的软件CXXFLAGS并不是一个好的选择。

相反,我建议创建一个包含命令的文件export CXXFLAGS='...'(用实际标志代替...),如上所示。然后,当您想要运行该命令时,您可以避免通过以下方式键入它:采购使用内置命令调用该文件.。如果该文件被调用cxxflags并且位于您的主目录中:

. ~/cxxflags

就像您手动运行export命令一样,您只需在 shell 中执行一次此操作。所有后续make命令都将使用 的新值CXXFLAGS,直到您exit退出当前 shell。make命令在单独的 shell 中运行会议不过,其他航站楼等的乘客则不会受到影响。

请注意,这是不是在这种情况下,您应该chmod +x在文件上运行并通过仅写入来运行它~/cxxflags。 这不会实现您想要的效果,因为它会CXXFLAGS在启动脚本的 shell 中分配并导出环境变量,然后脚本会立即退出,并且当前 shell 的环境不会受到影响。

如果你愿意,你可以编写一个别名或 shell 函数来设置和导出CXXFLAGS


为将来...

不幸的是,从命令行高效地编译 C++ 程序、了解所使用的方言以及获得合理有用的警告是多么复杂。(IDE 有相应的、甚至重叠的问题……但这并不会让那些还不熟悉命令行的用户轻松使用命令行。)信不信由你,我在这里建议的标志正是我建议新 C++ 程序员使用的标志从第一天开始

如果您已经有一些 C++ 经验(哪怕是一点点),您可能想要做更多。请随意忽略本节的其余部分!

-g发出调试符号;然后您可以使用类似的调试器gdb来调试程序。如果您以前使用过 IDE,它可能已经以这种方式编译了您的程序并与调试器集成。(您可以在 Ubuntu 中将 IDE 与调试器集成,并且有几种选择,但这超出了本文的范围。)

启动标志-O要求进行优化;最常见的是-Og,用于通常不会妨碍调试的优化;-O1,用于高度保守的优化;-O2,用于大多数速度优化;-O3试图挤出更多的速度,这有时有帮助,有时没有;和-Os,进行优化空间而不是速度。C 和 C++ 程序的调试版本通常不使用优化或-Og,而发布版本通常使用-O2-O3-Os

调试版本通常会受益于捕获并解释否则会导致令人困惑的崩溃或微妙的错误行为。-fsanitize=address,undefined通常是有帮助的。虽然这正是我喜欢向刚接触 C 或 C++ 的人(或来自清理器尚不支持的平台的人)推荐它,我避免在上面建议它,因为它有时会带来额外的复杂性。在某些系统上,必须安装额外的软件包才能支持它们;地址清理器 (Address Sanitizer) 的默认行为是在程序退出时打印有关内存泄漏的消息,即使由于程序在出现错误时故意退出,泄漏是可以接受的;当你确实要编译包含多个源代码文件的程序时,如果你分别编译它们(就像 makefile 所做的那样),你必须-fsanitize=...在链接时和编译时都传递它;它们与你可能链接到并从代码中使用的一些库不兼容;并且它们与一些其他工具(包括一些调试器)不兼容,或者需要额外的努力才能使用。

例如,方式更多工具建议,请参阅本章cpp最佳实践

别名和 Shell 函数

你问的是别名。你如果你真的想的话,可以创建一个 shell 别名。但它可能不会满足你的要求。bash 中的别名不接受参数;它们只是扩展到它们的定义中。你可以在命令中在它们后面写参数,但它们会出现在你写它们的末尾。你不能替换任何东西进入别名定义,因此您不能让参数filename出现在其中以代替其他文本。这就是为什么waltinator 演示改用 shell 函数。 Shell 函数比 shell 别名更强大、更灵活。

话虽如此,您可能希望拥有这样的别名:

alias mk='make CXXFLAGS="-std=c++17 -pedantic -Wall -Wextra"'

CXXFLAGS这是上述导出的替代方法。运行该别名定义后,您可以运行以使用这些编译器标志mk filename进行构建。如果您更喜欢这种方法,我建议将别名定义放在您的主目录中(如果没有,请创建该文件)。默认的每个用户文件源(如果存在),因此在新的交互式 bash shell 中,将定义别名。filename.cpp.bash_aliases.bashrc.bash_aliases

或者你可能想要定义CXXFLAGS但使用 shell 函数,如下所示沃尔蒂纳特的方式使用这些标志执行编译:

compile() { g++ $CXXFLAGS -o "$1" "$1.cpp"; }

如果没有CXXFLAGS变量,这仍然有效,但不会传递额外的标志。如果当前 shell 中定义了这样的变量,它会使用它——即使变量没有被导出。请注意,这是不常见的情况之一,在这种情况下,忽略参数扩展周围的双引号,即"$CXXFLAGS"。但是, 的扩展$1仍然应该被引用。

或者您可以在函数定义本身中包含所需的标志:

compile() { g++ -std=c++17 -pedantic -Wall -Wextra -o "$1" "$1.cpp"; }

最简单的情况是没有额外的标志,在这种情况下,你只需要另一种方式来编写所示的函数waltinator 的回答

compile() { g++ -o "$1" "$1.cpp"; }    

答案2

在中定义一个函数~/.bashrc

# Usage: docompile filename
function docompile ()
    {
    local objname="${1}"
    local srcname="${1}.cpp"
    g++ -o "$objname" "$srcname"
    }

答案3

linux:函数docompile(){objname="${srcname%.}” srcname="$1" g++ -o "$objname" "$1" } windows: function docompile () { objname="${srcname%.}“.exe srcname =“$1”g ++ -o“$objname”“$1”}

答案4

linux:函数docompile(){objname="${srcname%.}" srcname="$1" g++ -o "$objname" "$1" && ./$objname } shell:docompile youcpp(hello.cpp) shell:docompile hello.cpp windows: function docompile () { objname="${srcname%.}“.exe srcname =“$1”g ++ -o“$objname”“$1”}

相关内容