guides:software:make:start
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
guides:software:make:start [2020/07/20 14:48] – [Specifying a Single Target in a Makefile] wikiadmin | guides:software:make:start [2024/07/25 15:01] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 3: | Line 3: | ||
Make is a build automation tool that is designed to automatically construct executable programs from source code. | Make is a build automation tool that is designed to automatically construct executable programs from source code. | ||
+ | |||
+ | Make simplifies the build process for projects at all levels. | ||
===== Simple Use ===== | ===== Simple Use ===== | ||
Line 169: | Line 171: | ||
</ | </ | ||
+ | In the example: | ||
+ | - The user types //ls// to show the contents of the directory | ||
+ | - The user types //cat Makefile// to show the contents of the Makefile | ||
+ | - The user types //make// to build the default target //hello// | ||
+ | - The user types //ls// to show that hello was constructed | ||
+ | - The user types //make clean// to remove project executable files. | ||
+ | - The user types //ls// to show that the executable files have been removed. | ||
+ | |||
+ | The Makefile contains the following: | ||
<code make> | <code make> | ||
CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
Line 177: | Line 188: | ||
rm -f hello | rm -f hello | ||
</ | </ | ||
+ | |||
+ | Note that an additional target, //clean//, has been added to the Makefile. | ||
+ | - There are no dependencies | ||
+ | - There is a //rule// to be applied when building the target. | ||
+ | |||
+ | The rule is //rm -f hello// | ||
+ | |||
+ | Note that when constructing rules in make, the rules need to be indented by a tab. The following example demonstrates what would happen if //rm -f hello// were not preceded by a tab. | ||
+ | |||
+ | < | ||
+ | $ cat Makefile | ||
+ | CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | |||
+ | all: hello | ||
+ | |||
+ | clean: | ||
+ | rm -f hello | ||
+ | $ make | ||
+ | Makefile:6: *** missing separator. | ||
+ | </ | ||
+ | |||
+ | In this example: | ||
+ | - The user types //cat Makefile// to show the contents of the Makefile | ||
+ | - Notice that the rule for //clean// has a space and not a tab. | ||
+ | - The user types //make// to build the project | ||
+ | - Make reports an error because it can not parse the Makefile due to the missing tab. | ||
+ | |||
+ | It is extremely important that all rules for a target begin with a tab. | ||
+ | |||
+ | ===== Building Multiple Targets ===== | ||
+ | |||
+ | < | ||
+ | $ ls | ||
+ | Makefile | ||
+ | $ cat Makefile | ||
+ | CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | |||
+ | OBJS = hello greeting salute | ||
+ | |||
+ | all: ${OBJS} | ||
+ | |||
+ | clean: | ||
+ | rm -f ${OBJS} | ||
+ | $ make | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | $ ls | ||
+ | Makefile | ||
+ | $ make clean | ||
+ | rm -f hello greeting salute | ||
+ | $ ls | ||
+ | Makefile | ||
+ | </ | ||
+ | |||
+ | In this example: | ||
+ | - The user types //ls// to show the contents of the directory | ||
+ | - Note that three independent source code files exist // | ||
+ | - The user types //cat Makefile// to show the contents of the makefile. | ||
+ | - The changes will be explained below. | ||
+ | - The user types //make// to build all primary targets. | ||
+ | - Make constructs three executables, | ||
+ | - The user types //ls// to show the contents of the directory after the build. | ||
+ | - The user types //make clean// to clean up the project directory | ||
+ | - Make removes all of the executable files produced in the previous step. | ||
+ | - The user types //ls// to show the contents of the directory. | ||
+ | |||
+ | The makefile has been modified on three lines. | ||
+ | |||
+ | First, a variable called //OBJS// has been added. | ||
+ | |||
+ | <code make> | ||
+ | OBJS = hello greeting salute | ||
+ | </ | ||
+ | |||
+ | Secondly, the default target has been changed. | ||
+ | |||
+ | <code make> | ||
+ | all: ${OBJS} | ||
+ | </ | ||
+ | |||
+ | Finally, the rule to make clean has been altered to remove all of the files listed in the variable //OBJS//. | ||
+ | |||
+ | <code make> | ||
+ | clean: | ||
+ | rm -f ${OBJS} | ||
+ | </ | ||
+ | |||
+ | The final makefile for this section is: | ||
+ | <code make> | ||
+ | CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion | ||
+ | |||
+ | OBJS = hello greeting salute | ||
+ | |||
+ | all: ${OBJS} | ||
+ | |||
+ | clean: | ||
+ | rm -f ${OBJS} | ||
+ | </ | ||
+ | |||
===== Makefiles for Multiple File Compilation ===== | ===== Makefiles for Multiple File Compilation ===== | ||
+ | |||
+ | One of the most powerful uses of make is to compile multiple files into a single executable. | ||
+ | |||
+ | ==== Example ==== | ||
+ | |||
+ | For this example the code is decomposed into the following files: | ||
+ | |||
+ | * // | ||
+ | * <code c++> | ||
+ | #ifndef STRING_TOOLS | ||
+ | #define STRING_TOOLS | ||
+ | |||
+ | void LowerCase(std:: | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | * // | ||
+ | * <code c++> | ||
+ | include < | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | void LowerCase(string & word){ | ||
+ | for(auto &x : word) { | ||
+ | x = static_cast< | ||
+ | } | ||
+ | |||
+ | return; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * // | ||
+ | * <code c++> | ||
+ | #ifndef GREETING | ||
+ | #define GREETING | ||
+ | |||
+ | std::string GreetingString(std:: | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | * // | ||
+ | * <code c++> | ||
+ | |||
+ | #include < | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | string GreetingString(string language){ | ||
+ | string greeting = "Hello World"; | ||
+ | |||
+ | LowerCase(language); | ||
+ | |||
+ | if (language == " | ||
+ | | ||
+ | } else if (language == " | ||
+ | | ||
+ | } | ||
+ | |||
+ | return greeting; | ||
+ | } | ||
+ | </ | ||
+ | * // | ||
+ | * <code c++> | ||
+ | #include < | ||
+ | |||
+ | #include " | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | int main() { | ||
+ | string languages[] = {" | ||
+ | |||
+ | for (auto lang: languages) { | ||
+ | cout << " The greeting in \"" | ||
+ | cout << GreetingString(lang) << " | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | * // | ||
+ | * <code make> | ||
+ | CXXFLAGS = -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wu | ||
+ | ninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | |||
+ | OBJS = hello | ||
+ | |||
+ | all: ${OBJS} | ||
+ | |||
+ | hello: greeting.o stringTools.o | ||
+ | |||
+ | greeting.o: greeting.h stringTools.h | ||
+ | |||
+ | stringTools.o: | ||
+ | |||
+ | clean: | ||
+ | rm -f ${OBJS} *.o | ||
+ | </ | ||
+ | |||
+ | To build this code, you are required to compile stringTools.cpp into stringTools.o, | ||
+ | |||
+ | This could be accomplished by hand by executing the following | ||
+ | < | ||
+ | g++ -c greeting.cpp | ||
+ | g++ -c stringTools.cpp | ||
+ | g++ -o hello hello.cpp stringTools.o greeting.o | ||
+ | </ | ||
+ | |||
+ | Of course, if you have command line flags, this becomes much more complex. | ||
+ | |||
+ | Using the above // | ||
+ | |||
+ | < | ||
+ | $ make | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | $ ls | ||
+ | Makefile | ||
+ | greeting.cpp | ||
+ | </ | ||
+ | |||
+ | Note that all components are compiled and the final executable is produced. | ||
+ | |||
+ | < | ||
+ | $ touch greeting.cpp | ||
+ | $ make | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion -std=c++14 | ||
+ | </ | ||
+ | |||
+ | ==== The Makefile ==== | ||
+ | |||
+ | In order to build this project using make, you need to inform make of the dependencies built into the project. | ||
+ | |||
+ | <code make> | ||
+ | hello: | ||
+ | </ | ||
+ | |||
+ | You do not need to tell make that //hello// depends on // | ||
+ | |||
+ | You also do not need to tell make that //hello// depends on // | ||
+ | |||
+ | <code make> | ||
+ | stringTools.o: | ||
+ | </ | ||
+ | |||
+ | This line tells make that // | ||
+ | |||
+ | <code make> | ||
+ | greeting.o: greeting.h stringTools.h | ||
+ | </ | ||
+ | |||
+ | This line tells make that // | ||
guides/software/make/start.1595256526.txt.gz · Last modified: 2024/07/25 15:01 (external edit)