How do I create an alias in my .bashrc file so that I can compile my C++ program without inputting this much longer command:

g++ -o filename filename.cpp

Here the file name is variable.


TL;DR: Use make filename instead. Consider setting and exporting CXXFLAGS for warnings.

If you're really only interested in running g++ -o filename filename.cpp (with no options to enable compiler warnings or otherwise customize the behavior of the compiler) you can read just the first section, immediately below. For coverage of alternate approaches that do use shell aliases and shell functions, see the very last section.

This answer focuses on C++ but much of it applies to C. The major difference is that flags make passes to compile a C source code file are taken from CFLAGS rather than CXXFLAGS.


You can just pass the basename to make.

As steeldriver says, a better solution than a shell function or shell alias is to take advantage of make's implicit rules. Running your command g++ -o filename filename.cpp has the same effect as

make filename

...unless filename exists and is no older than filename.cpp, in which case make refrains from compiling it again and instead reports make: 'filename' is up to date, which is what you likely want in that situation. When you change your source code file, it becomes newer than the last-compiled executable (if any), so a subsequent invocation of make filename recompiles it.

As steeldriver mentioned, you should only have one source code file with filename as its basename to use this method. If you have source code files for multiple languages, like filename.c, filename.cpp, and filename.m, then make will pick one according to its rules, and it won't necessarily be the one you intend.

Running make without a makefile also only works if your program only requires one source code file. But that seems to be the case here, and is also most often the case when one starts out learning to program in C or C++.

The command make actually runs to compile a C++ source code file is not actually g++, but is instead c++. However, c++ on Ubuntu (and most GNU/Linux systems) is typically a symbolic link that resolves to the g++ command, unless you've deliberately changed it or only installed some other C++ compiler.

You should enable warnings, and usually pick a dialect.

With very few exceptions, such as checking that your compiler works at all, you should enable compiler warnings. This tells your compiler to warn you about code that is likely to contain mistakes. By default, most C and C++ compilers, including the popular compilers GCC and Clang (the g++ and clang++ commands) warn about very few things. I'll describe how to run g++ with warnings enabled, then I'll show how to make make enable warnings when you run make filename.

At minimum, use -Wall, which for historical reasons and contrary to its name doesn't actually enable all warnings. You should also nearly always use -Wextra. You can enable additional warnings individually (run man g++ to see all of them, if you like), but this is a good start and often a reasonable choice even for a large software project.

I don't know how much C++ experience you currently have. Experienced programmers typically use and benefit greatly from warnings, but if you're new to the language, you still shouldn't wait to start using them. This is because they can save you a lot of headache in finding otherwise vexing bugs in your programs, and because they can help you avoid making common mistakes and developing bad habits.

The command g++ -o filename filename.cpp doesn't ask for any but the small number of default warnings. The corresponding command g++ -Wall -Wextra -o filename filename.cpp enables -Wall and -Wextra. You can put -Wall and -Wextra anywhere in the command except between -o and filename or before g++.

If you want to try out -Wall and -Wextra one time, you can run make like this:

make CXXFLAGS='-Wall -Wextra' filename

Note that this still won't recompile filename.cpp if the source code is no newer than the executable, even if you didn't pass CXXFLAGS='-Wall -Wextra' to make last time you ran it.

As you can see, that's fairly cumbersome; your whole goal is to compile your small programs with a minimum of typing. Fortunately, in addition to accepting assignments to its CXXFLAGS variable on the command-line, make also respects the CXXFLAGS environment variable if there is one. So you can run

export CXXFLAGS='-Wall -Wextra'

and then subsequent runs of make filename will pass the -Wall and -Wextra flags to the C++ compiler automatically. However, this is not permanent; in other shells (that are not started from this one) it does not apply.

I'll get to how you can avoid having to type that soon. But first...

You should pick a dialect, and consider -pedantic for more warnings.

You should also tell g++ what dialect of C++ you are using. For example, if you are using C++17 without GNU extensions, pass the -std=c++17 option. As of this writing, C++17 is the current standard dialect of C++. If you're learning C++ and you're not sure what dialect you want, you could consult whatever materials you're learning from or consult your instructor (if any). If none of that applies, I suggest using the current standard, assuming your compiler supports it. Telling the compiler -std=c++17 does not force you to use all the newest features of C++ in your programs. If you want C++17 with GNU extensions, you'd use -std=gnu++17; if you don't know or care about the difference, then -std=c++17 is reasonable.

If you don't tell g++ what dialect you want, it will use its default, which varies across different versions of GCC. Specifying the dialect you want helps the compiler issue errors and warnings when your code is incorrect (or suspicious) when considered to be written in that particular dialect. It also helps the compiler not issue errors and warnings that might not be appropriate for the dialect you are using, because without it, the compiler assumes you're using whatever its default is.

If you tell g++ what dialect you want, and it is one of the standard dialects (e.g., if you use -std=c++17, not -std=gnu++17), then you can enable more warnings than would otherwise be shown, about code that does not conform to that dialect, by passing g++ the -pedantic flag. Some of those warnings actually apply to all or most standard dialects. If you want such code to cause errors to be issued--causing the compiler to deliberately fail and refuse to generate an executable even if it otherwise could--then you can use -pedantic-errors.

You can pass those flags even if you don't specific a dialect or if the dialect you specify isn't one the ones that is standardized, but you probably wouldn't want to, because it would be hard to judge if they are reasonable, and you'd likely end up ignoring a lot of them. You can also turn all warnings into errors with -Werror, which is a somewhat popular practice, because it makes it impossible to ignore warnings. However, if you're just starting out, I suggest against doing this, even though warnings should not be ignored except in extremely unusual cases. It is sometimes handy to get code to compile with warnings, try it out, and then fix the problems that caused the warnings.

To include -std=c++17 and -pedantic in your CXXFLAGS:

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

If you've already exported CXXFLAGS in your shell, you can omit export on subsequent assignments. But there is no harm in keeping it.

You can put your export command in a file, then source it with ..

You can set CXXFLAGS the way you would set most environment variables, like PATH, for example by putting the export command for it in ~/.profile. But I recommend against this, because you may build software with make that was written by other authors, for which your usually preferred CXXFLAGS aren't a good choice.

Instead, I suggest making a file that contains an export CXXFLAGS='...' command (with your actual flags in place of ...) such as the one shown above. Then, when you want to run that command, you can avoid having to type it by sourcing that file with the . builtin. If the file is called cxxflags and is in your home directory:

. ~/cxxflags

Like if you ran the export command manually, you only have to this once in your shell. All your subsequent make commands will use the new value of CXXFLAGS, until you exit out of the current shell. make command run in separate shell sessions, however, such as those in other terminals, will not be affected.

Note that this is not a situation where you should run chmod +x on the file and run it by just writing ~/cxxflags. This wouldn't do what you want, because it would assign and export the CXXFLAGS environment variable in the shell started to run the script, which would immediately exit afterwards, and the current shell's environment would be unaffected.

If you prefer, you could instead write an alias or shell function that sets and exports CXXFLAGS.


For the future...

It is somewhat unfortunate how complicated it is to efficiently compile C++ programs from the command line, know what dialect you are using, and get reasonably helpful warnings. (IDEs have corresponding, even overlapping problems... but that doesn't make the command-line situation easy for users who aren't yet comfortable with it.) Believe it or not, the flags I've suggested here are just the ones I recommend new C++ programmers use from day one.

If you already have some C++ experience (even a little), you may want to do more. Feel free to ignore the rest of this section!

-g emits debug symbols; then you can use a debugger like gdb to debug your program. If you previously used an IDE, it may already have compiled your programs in this way and integrated with a debugger. (You can integrate an IDE with a debugger in Ubuntu and there are several choices, but that is beyond the scope of this post.)

Flags that start -O call for optimizations; the most common are -Og, for optimizations that don't usually get in the way of debugging; -O1, for highly conservative optimizations; -O2, for most speed optimizations; -O3 to try to squeeze out even more speed, which sometimes helps and sometimes doesn't; and -Os, to optimize for space rather than speed. Debug builds of C and C++ programs usually use either no optimizations or -Og, while release builds usually use -O2, -O3, or -Os.

Debug builds often benefit from sanitizers that catch and explain problems that would otherwise cause a confusing crash or subtle wrong behavior. -fsanitize=address,undefined is often helpful. Although this is exactly the sort of thing I'd like to recommend to people who are new to C or C++ (or who are coming from platforms that sanitizers don't yet support), I've avoided suggesting it above because it sometimes introduces additional complexity. On some systems, additional packages must be installed to support them; the default behavior of Address Sanitizer is to print messages about memory leaks when a program quits even if the leaks were acceptable because the program deliberately bailed out during an error; when you do get into compiling programs with multiple source code files, if you compile them separately (as a makefile would do) you must pass -fsanitize=... at link-time as well as compile-time; they are incompatible with some libraries you might link to and use from your code; and they are incompatible, or require additional effort to be used, with some other tools, including some debuggers.

For way, way more tooling suggestions, see this chapter of cppbestpractices.

Aliases and Shell Functions

You asked about an alias. You can create a shell alias, if you really want to. But it may not do what you want. Aliases in bash don't accept arguments; they simply expand into their definitions. You can write arguments after them in a command, but they appear at the end where you wrote them. You cannot substitute anything into an alias definition, so you cannot cause an argument filename to appear inside it in place of some other text. This is why waltinator demonstrated a shell function instead. Shell functions are much more powerful and versatile than shell aliases.

With that said, you might like to have an alias like this:

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

This is an alternative to exporting CXXFLAGS as described above. Once that alias definition has been run, you can run mk filename to build filename.cpp with those compiler flags. If you prefer this approach, I suggest putting the alias definition in .bash_aliases in your home directory (create the file if it doesn't). The default per-user .bashrc file sources .bash_aliases if it exists, so in new interactive bash shells, the alias will be defined.

Or perhaps you want to define CXXFLAGS but use a shell function as in waltinator's way to perform the compilation with those flags:

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

If there is no CXXFLAGS variable, this still works, but passes no extra flags. If there is such a variable defined in the current shell, it uses it--even if the variable is not exported. Note that this is one of the uncommon situations where it is correct to omit the double quotes around parameter expansion, i.e., don't write "$CXXFLAGS". However, the expansions of $1 should still be quoted.

Or you can include the flags you want in the function definition itself:

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

The simplest case is that of no extra flags, in which case you get just another way to write the function shown in waltinator's answer.

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