comparison src/Large.v @ 243:b2c72c77ad47

Build Processes
author Adam Chlipala <adamc@hcoop.net>
date Wed, 09 Dec 2009 13:59:01 -0500
parents 5a32784e30f3
children 4662b6f099b0
comparison
equal deleted inserted replaced
242:5a32784e30f3 243:b2c72c77ad47
727 Theorem unique_ident : forall e', (forall a, e' + a = a) -> e' = 0. 727 Theorem unique_ident : forall e', (forall a, e' + a = a) -> e' = 0.
728 exact IntTheorems.unique_ident. 728 exact IntTheorems.unique_ident.
729 Qed. 729 Qed.
730 730
731 (** As in ML, the module system provides an effective way to structure large developments. Unlike in ML, Coq modules add no expressiveness; we can implement any module as an inhabitant of a dependent record type. It is the second-class nature of modules that makes them easier to use than dependent records in many case. Because modules may only be used in quite restricted ways, it is easier to support convenient module coding through special commands and editing modes, as the above example demonstrates. An isomorphic implementation with records would have suffered from lack of such conveniences as module subtyping and importation of the fields of a module. *) 731 (** As in ML, the module system provides an effective way to structure large developments. Unlike in ML, Coq modules add no expressiveness; we can implement any module as an inhabitant of a dependent record type. It is the second-class nature of modules that makes them easier to use than dependent records in many case. Because modules may only be used in quite restricted ways, it is easier to support convenient module coding through special commands and editing modes, as the above example demonstrates. An isomorphic implementation with records would have suffered from lack of such conveniences as module subtyping and importation of the fields of a module. *)
732
733
734 (** * Build Processes *)
735
736 (** As in software development, large Coq projects are much more manageable when split across multiple files and when decomposed into libraries. Coq and Proof General provide very good support for these activities.
737
738 Consider a library that we will name [Lib], housed in directory %\texttt{%#<tt>#LIB#</tt>#%}% and split between files %\texttt{%#<tt>#A.v#</tt>#%}%, %\texttt{%#<tt>#B.v#</tt>#%}%, and %\texttt{%#<tt>#C.v#</tt>#%}%. A simple Makefile will compile the library, relying on the standard Coq tool %\texttt{%#<tt>#coq_makefile#</tt>#%}% to do the hard work.
739
740 <<
741 MODULES := A B C
742 VS := $(MODULES:%=%.v)
743
744 .PHONY: coq clean
745
746 coq: Makefile.coq
747 make -f Makefile.coq
748
749 Makefile.coq: Makefile $(VS)
750 coq_makefile -R . Lib $(VS) -o Makefile.coq
751
752 clean:: Makefile.coq
753 make -f Makefile.coq clean
754 rm -f Makefile.coq
755 >>
756
757 The Makefile begins by defining a variable %\texttt{%#<tt>#VS#</tt>#%}% holding the list of filenames to be included in the project. The primary target is %\texttt{%#<tt>#coq#</tt>#%}%, which depends on the construction of an auxiliary Makefile called %\texttt{%#<tt>#Makefile.coq#</tt>#%}%. Another rule explains how to build that file. We call %\texttt{%#<tt>#coq_makefile#</tt>#%}%, using the %\texttt{%#<tt>#-R#</tt>#%}% flag to specify that files in the current directory should be considered to belong to the library [Lib]. This Makefile will build a compiled version of each module, such that %\texttt{%#<tt>#X.v#</tt>#%}% is compiled into %\texttt{%#<tt>#X.vo#</tt>#%}%.
758
759 Now code in %\texttt{%#<tt>#B.v#</tt>#%}% may refer to definitions in %\texttt{%#<tt>#A.v#</tt>#%}% after running
760
761 [[
762 Require Import Lib.A.
763
764 ]]
765
766 Library [Lib] is presented as a module, containing a submodule [A], which contains the definitions from %\texttt{%#<tt>#A.v#</tt>#%}%. These are genuine modules in the sense of Coq's module system, and they may be passed to functors and so on.
767
768 [Require Import] is a convenient combination of two more primitive commands. [Require] finds the %\texttt{%#<tt>#.vo#</tt>#%}% file containing the named module, ensuring that the module is loaded into memory. [Import] loads all top-level definitions of the named module into the current namespace, and it may be used with local modules that do not have corresponding %\texttt{%#<tt>#.vo#</tt>#%}% files. Another command, [Load], is for inserting the contents of a named file verbatim. It is generally better to use the module-based commands, since they avoid rerunning proof scripts, and they facilitate reorganization of directory structure without the need to change code.
769
770 Now we would like to use our library from a different development, called [Client] and found in directory %\texttt{%#<tt>#CLIENT#</tt>#%}%, which has its own Makefile.
771
772 <<
773 MODULES := D E
774 VS := $(MODULES:%=%.v)
775
776 .PHONY: coq clean
777
778 coq: Makefile.coq
779 make -f Makefile.coq
780
781 Makefile.coq: Makefile $(VS)
782 coq_makefile -R LIB Lib -R . Client $(VS) -o Makefile.coq
783
784 clean:: Makefile.coq
785 make -f Makefile.coq clean
786 rm -f Makefile.coq
787 >>
788
789 We change the %\texttt{%#<tt>#coq_makefile#</tt>#%}% call to indicate where the library [Lib] is found. Now %\texttt{%#<tt>#D.v#</tt>#%}% and %\texttt{%#<tt>#E.v#</tt>#%}% can refer to definitions from [Lib] module [A] after running
790
791 [[
792 Require Import Lib.A.
793
794 ]]
795
796 and %\texttt{%#<tt>#E.v#</tt>#%}% can refer to definitions from %\texttt{%#<tt>#D.v#</tt>#%}% by running
797
798 [[
799 Require Import Client.D.
800
801 ]]
802
803 It can be useful to split a library into several files, but it is also inconvenient for client code to import library modules individually. We can get the best of both worlds by, for example, adding an extra source file %\texttt{%#<tt>#Lib.v#</tt>#%}% to [Lib]'s directory and Makefile.
804
805 [[
806 Require Export Lib.A Lib.B Lib.C.
807
808 ]]
809
810 Now client code can import all definitions from all of [Lib]'s modules simply by running
811
812 [[
813 Require Import Lib.
814
815 ]]
816
817 The two Makefiles above share a lot of code, so, in practice, it is useful to define a common Makefile that is included by multiple library-specific Makefiles.
818
819 %\medskip%
820
821 The remaining ingredient is the proper way of editing library code files in Proof General. Recall this snippet of %\texttt{%#<tt>#.emacs#</tt>#%}% code from Chapter 2, which tells Proof General where to find the library associated with this book.
822
823 <<
824 (custom-set-variables
825 ...
826 '(coq-prog-args '("-I" "/path/to/cpdt/src"))
827 ...
828 )
829 >>
830
831 To do interactive editing of our current example, we just need to change the flags to point to the right places.
832
833 <<
834 (custom-set-variables
835 ...
836 ; '(coq-prog-args '("-I" "/path/to/cpdt/src"))
837 '(coq-prog-args '("-R" "LIB" "Lib" "-R" "CLIENT" "Client"))
838 ...
839 )
840 >>
841
842 When working on multiple projects, it is useful to leave multiple versions of this setting in your %\texttt{%#<tt>#.emacs#</tt>#%}% file, commenting out all but one of them at any moment in time. To switch between projects, change the commenting structure and restart Emacs. *)