国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
1.16. Building a Static Library with GNU Make

1.16. Building a Static Library with GNU Make

Problem

You want to use GNU make to build a static library from a collection of C++ source files, such as those listed in Example 1-1.

Solution

First, create a makefile in the directory where you want your static library to be created, and declare a phony target all whose single prerequisite is the static library. Next, declare your static library target. Its prerequisites should be the object files that the library will contain, and its command script should be a command line to build the library from the collection of object files, as demonstrated in Recipe 1.3. If you are using GCC or a compiler with similar command-line syntax, customize the implicit patterns rules, if necessary, by modifying one or more of the variables CXX, CXXFLAGS, etc. used in make's database of implicit rules, as shown in Recipe 1.15. Otherwise, write a pattern rule telling make how to compile .cpp files into object files, using the command lines from Table 1-4 and the pattern rule syntax explained in Recipe 1.16. Next, declare targets indicating how each of your library's source files depends on the headers it includes, directly or indirectly. You can write these dependencies by hand or arrange for them to be generated automatically. Finally, add install and clean targets as demonstrated in Recipe 1.15.

For example, to build a static library from the source files listed in Example 1-2 using GCC on Unix, create a makefile in the directory johnpaul, as shown in Example 1-20.

Example 1-20. Makefile for libjohnpaul.a using GCC on Unix

# Specify extensions of files to delete when cleaningCLEANEXTS   = o a # Specify the target file and the install directoryOUTPUTFILE  = libjohnpaul.aINSTALLDIR  = ../binaries# Default target.PHONY: allall: $(OUTPUTFILE)# Build libjohnpaul.a from john.o, paul.o, and johnpaul.o$(OUTPUTFILE): john.o paul.o johnpaul.o    ar ru $@ $^    ranlib $@# No rule to build john.o, paul.o, and johnpaul.o from .cpp # files is required; this is handled by make's database of# implicit rules.PHONY: installinstall:    mkdir -p $(INSTALLDIR)    cp -p $(OUTPUTFILE) $(INSTALLDIR).PHONY: clean clean:    for file in $(CLEANEXTS); do rm -f *.$$file; done# Indicate dependencies of .ccp files on .hpp filesjohn.o: john.hpppaul.o: paul.hppjohnpaul.o: john.hpp paul.hpp johnpaul.hpp

Similarly, to build a static library using Visual C++, your makefile might look as shown in Example 1-21.

Example 1-21. Makefile for libjohnpaul.lib using Visual C++

# Specify extensions of files to delete when cleaningCLEANEXTS      = obj lib # Specify the target file and the install directoryOUTPUTFILE     = libjohnpaul.libINSTALLDIR     = ../binaries# Pattern rule to build an object file from a .cpp file%.obj: %.cpp    "$(MSVCDIR)/bin/cl" -c -nologo -EHsc -GR -Zc:forScope -Zc:wchar_t             $(CXXFLAGS) $(CPPFLAGS) -Fo"$@" $<# Default target.PHONY: allall: $(OUTPUTFILE)# Build libjohnpaul.lib from john. obj, paul. obj, and johnpaul. obj$(OUTPUTFILE): john.obj paul.obj johnpaul.obj    "$(MSVCDIR)/bin/link" -lib -nologo -out:"$@" $^.PHONY: installinstall:    mkdir -p $(INSTALLDIR)    cp -p $(OUTPUTFILE) $(INSTALLDIR).PHONY: clean clean:    for file in $(CLEANEXTS); do rm -f *.$$file; done# Indicate dependency of .cpp files on .hpp filesjohn.obj: john.hpppaul.obj: paul.hppjohnpaul. obj: john.hpp paul.hpp johnpaul.hpp

Tip

In Example 1-21, I've expressed Visual C++'s link.exe command as "$(MSVCDIR)/bin/link", using the environment variable MSVCDIR set by vcvars32.bat. This prevents confusion between the Visual C++ linker and the Unix link command, supported by Cygwin and MSYS. For consistency, I've also expressed Visual C++'s compile command using MSVCDIR.

Discussion

Let's walk through Example 1-20. I start by defining variables to represent the output file, the install directory, and the extensions of files that should be deleted when the target clean is built. Next, I declare the default target all, as in Example 1-14.

The rule to build the static library looks like this:

$(OUTPUTFILE): john.o paul.o johnpaul.o    ar ru $@ $^    ranlib $@

It's a straightforward adaptation of the entry for GCC in Table 1-10. Here $(OUTPUTFILE) and $@ both expand to libjohnpaul.a, and $^ expands to the list of prerequisites john.o paul.o johnpaul.o.

The next two rules declare install and clean targets, as in Recipe 1.15. The only difference is that in Example 1-20 I use a shell looping construct to remove all files whose extension appears in the list o a — i.e., all object or static library files:

for file in $(CLEANEXTS); do rm -f *.$$file; done

I've used a double dollar sign to prevent make from expanding the variable $$file rather than passing it on to the shell.

The last three rules specify the dependency relationships between the library's .cpp files and the headers they include. There's one rule for each .cpp file; its target is the object file to be built from the .cpp file, and its prerequisites are the header files included—directly or indirectly—by the .cpp file:

john.o: john.hpppaul.o: paul.hppjohnpaul.o: john.hpp paul.hpp johnpaul.hpp

This can be understood as follows. If a .cpp file includes a header file—directly or indirectly—it must be rebuilt each time the header is modified. However, since the .cpp file exists and does not appear as the target of any rule, it is never out of date, as discussed in Recipe Recipe 1.15. Consequently, when the header is modified, no recompilation is triggered. The fix is to declare a rule making these dependencies explicit; whenever one of the headers in question is modified, the object file corresponding to the .cpp will become out of date, causing the .cpp file to be recompiled.

This solution is only adequate for very small projects, since it's extremely difficult to keep the targets representing source file dependencies synchronized with a changing codebase. Fortunately, there are several methods for generating these dependencies automatically. For example, you can replace the last three rules in Example 1-20 with the following:

# Generate dependencies of .ccp files on .hpp filesinclude john.o paul.o johnpaul.o%.d: %.cpp    $(CC) -M $(CPPFLAGS) $< > $@.$$$$;     sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;     rm -f $@.$$$$

This bit of code relies on the compiler option -M which causes GCC to output dependency information for inclusion in a makefile. For a detailed explanation of how it works—and why it's sometimes inadequate—see Managing Projects with GNU make, Third Edition, by Robert Mecklenburg (O'Reilly).

Tip

Put the code to generate dependencies at the end of your makefile.

This method can be adapted to work with most toolsets, since most compilers provide an option similar to GCC's -M; in fact, the option is usually either -M or -m. Visual C++, however, does not provide an option for generating makefile dependencies. If you use Visual C++, you have two choices. You can use the -Gm option, together with one of the options -Zi or -ZI, discussed in Recipe 1.16. The -Gm option tells the compiler to build a database, stored in a file with the extension idb, containing information about dependencies between source files. The .idb file is created when a .cpp file, or collection of .cpp files, is initially compiled. On subsequent compilations, only those source files which have been modified or which depend on headers which have been modified are recompiled.

Alternatively, you can use the -showIncludes option, together with the option -E. The -showIncludes option causes the compiler to output a message to standard error each time an include directive is encountered. The -E option tells the compiler to run the preprocessor and then exit, without building any binary files. Using a bit of shell scripting, you can use the output generated by -showIncludes to construct makefile dependencies:

include john.d paul.d johnpaul.d%.d: %.cpp    "$(MSVCDIR)/bin/cl" -E -showIncludes $< 2> $@.$$$$ > /dev/null;     sed -n 's/^Note: including file: *\(.*\)/$*.obj·$*.d:\1/gp'         < $@.$$$$ | sed 's:\\:/:g;s: :\\ :gp' > $@;             \                               rm -f $@.$$$$

In this example, the character · represents a Tab.

Let's make one last improvement to Example 1-20. Currently, the sequence john paul johnpaul occurs in two places; in the prerequisites of the rule to build the static library, and in the include directive used to generate dependencies. If the list of source files changes, you'll have to update the makefile in two locations. It's better to define a variable SOURCES, and to replace both occurrences of the sequence john paul johnpaul with expressions involving SOURCES:

SOURCES = john.cpp paul.cpp johnpaul.cpp...# Build libjohnpaul.a from john.o, paul.o, and johnpaul.o$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))    ar ru $@ $^    ranlib $@...    # Generate dependencies of .ccp files on .hpp filesinclude $(subst .cpp,.d,$(SOURCES))%.d: %.cpp    $(CC) -M $(CPPFLAGS) $< > $@.$$$$;     sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;     rm -f $@.$$$$

Here I'm using the make function $(subst x,y,str), which replaces x with y everywhere in str.

Tip

GNU make supports a rich collection of functions for string and filename manipulation and more. It also supports user defined functions. As usual, for a thorough treatment, see Managing Projects with GNU make, Third Edition, by Robert Mecklenburg (O'Reilly).

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
HOWTO Specify the Header File Include Path for use with MinGW Compilers | MinGW
makefile自動(dòng)依賴和隱式規(guī)則測(cè)試,順便探討下通用的makefile的寫法
萬能makefile寫法詳解,一步一步寫一個(gè)實(shí)用的makefile,詳解 sed s
Jan07
view | bill gatliff.com
Getting Started with the LLVM System — LLVM 16.0.0...
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服