// file : libbuild2/install/rule.hxx -*- C++ -*- // license : MIT; see accompanying LICENSE file #ifndef LIBBUILD2_INSTALL_RULE_HXX #define LIBBUILD2_INSTALL_RULE_HXX #include #include #include #include #include #include #include namespace build2 { namespace install { class LIBBUILD2_SYMEXPORT alias_rule: public simple_rule { public: virtual bool match (action, target&) const override; // Return NULL if this prerequisite should be ignored and pointer to its // target otherwise. In the latter case, return the match options that // should be used for this prerequisite (use match_extra::all_options // and not 0 if no match options are needed). // // The default implementation ignores prerequsites that are outside of // the installation scope (see install_scope() for details). // // The default implementation always returns match_extra::all_options. // The match_extra argument is not used by the default implementation. // // The prerequisite is passed as an iterator allowing the filter to // "see" inside groups. // using prerequisite_iterator = prerequisite_members_range::iterator; virtual pair filter (const scope*, action, const target&, prerequisite_iterator&, match_extra&) const; virtual pair filter (const scope*, action, const target&, const prerequisite&, match_extra&) const; // Note: rule::apply() override (with match_extra). // virtual recipe apply (action, target&, match_extra&) const override; // Implementation of apply(). // // If the implementation may call reapply_impl(), then the reapply // argument to apply_impl() must be true. Note that in this case, the // *_impl() functions use the prerequisite_target::data member for own // housekeeping. // recipe apply_impl (action, target&, match_extra&, bool reapply = false) const; // Implementation of reapply() that re-tries prerequisites that have // been filtered out during the reapply() call. Note that currently not // supported for update, only for install/uninstall. // void reapply_impl (action, target&, match_extra&) const; alias_rule () {} static const alias_rule instance; private: virtual recipe apply (action, target&) const override; // Dummy simple_rule override. }; // In addition to the alias rule's semantics, this rule sees through to // the group's members. // // The default group_rule::instance matches any target for which it was // registered. It is to be used for non-see-through groups that should // exhibit the see-through behavior for install (see lib{} in the bin // module for an example). // // We also register (for all targets) another instance of this rule that // only matches see-through groups. // class LIBBUILD2_SYMEXPORT group_rule: public alias_rule { public: virtual bool match (action, target&) const override; // Return false if this group member should be ignored and true // otherwise. Note that this filter is called during apply(). // // The default implementation accepts all members. // virtual bool filter (action, const target&, const target& group_member) const; // Return NULL if this prerequisite should be ignored and pointer to its // target otherwise. The same semantics as in file_rule below. // virtual pair filter (const scope*, action, const target&, const prerequisite&, match_extra&) const override; using alias_rule::filter; // "Unhide" to make Clang happy. virtual recipe apply (action, target&, match_extra&) const override; group_rule (bool sto = false): see_through_only (sto) {} static const group_rule instance; bool see_through_only; }; struct install_dir; class LIBBUILD2_SYMEXPORT file_rule: public simple_rule { public: virtual bool match (action, target&) const override; // Return false if this ad hoc group member should be ignored and true // otherwise. Note that this filter is called during execute and only // for install/uninstall (and not update). For generality, it is also // (first) called on the target itself (can be detected by comparing // the second and third arguments). // // The default implementation accepts all members. // virtual bool filter (action, const target&, const target& adhoc_group_member) const; // Return NULL if this prerequisite should be ignored and pointer to its // target otherwise. In the latter case, return the match options that // should be used for this prerequisite (use match_extra::all_options // and not 0 if no match options are needed). // // The default implementation ignores prerequsites that are outside of // the installation scope (see install_scope() for details). It also // ignores exe{} prerequisites assuming an exe{} listed for a file // target is there to execute (e.g., to generate that target) and // normally should not be installed (an exe{} would typically be // installed via the dir{./} alias). But this can be overridden with a // prerequisite-specific install=true, for example: // // exe{foo}: exe{bar}: install = true # foo runs bar // // The default implementation always returns match_extra::all_options. // The match_extra argument is not used by the default implementation. // // The prerequisite is passed as an iterator allowing the filter to // "see" inside groups. // using prerequisite_iterator = prerequisite_members_range::iterator; virtual pair filter (const scope*, action, const target&, prerequisite_iterator&, match_extra&) const; virtual pair filter (const scope*, action, const target&, const prerequisite&, match_extra&) const; // Note: rule::apply() override (with match_extra). // virtual recipe apply (action, target&, match_extra&) const override; // Implementation of apply() that returns empty_recipe (i.e., NULL) if // the target is not installable. // // If the implementation may call reapply_impl(), then the reapply // argument to apply_impl() must be true. Note that in this case, the // *_impl() functions use the prerequisite_target::data member for own // housekeeping. // recipe apply_impl (action, target&, match_extra&, bool reapply = false) const; // Implementation of reapply() that re-tries prerequisites that have // been filtered out during the reapply() call. Note that currently not // supported for update, only for install/uninstall. // void reapply_impl (action, target&, match_extra&) const; static target_state perform_update (action, const target&); // Extra un/installation hooks. Return true if anything was actually // un/installed. // using install_dir = install::install_dir; // For derived rules. virtual bool install_extra (const file&, const install_dir&) const; virtual bool uninstall_extra (const file&, const install_dir&) const; // Lower-level pre/post installation hooks that can be used to override // the source file path being installed (for example, to implement // post-processing, etc). // // Note that one cannot generally perform post-processing in-place // because of permissions. // virtual auto_rmfile install_pre (const file&, const install_dir&) const; virtual bool install_post (const file&, const install_dir&, auto_rmfile&&) const; // Installation/uninstallation "commands". // // The verbosity argument specified the level to start printing the // command at. Note that these functions respect the dry_run flag. // Install (create) a directory: // // install -d // // Note: is expected to be absolute. // // Note that the target argument only specifies which target caused // this directory to be created. // static void install_d (const scope& rs, const install_dir& base, const dir_path& dir, const file& target, uint16_t verbosity = 1); // Install a file: // // install / # if is empty // install / # if is not empty // // Note that should be a simple path. // static void install_f (const scope& rs, const install_dir& base, const path& name, const file& target, const path& file, uint16_t verbosity = 1); // Install (make) a symlink: // // install -l / // // Which is essentially: // // ln -s / // // Note that should be a simple path. Note that // must not be absolute if relocatable installation is requested // (config.install.relocatable). // // Note that the target argument only specifies which target this // symlink "belongs" to. // static void install_l (const scope& rs, const install_dir& base, const path& link, const file& target, const path& link_target, uint16_t verbosity = 1); // Uninstall (remove) a file or symlink: // // uninstall / # rm /.leaf (); name empty // uninstall # rm /; target can be NULL // // Return false if nothing has been removed (i.e., the file does not // exist). // static bool uninstall_f (const scope& rs, const install_dir& base, const file* target, const path& name, uint16_t verbosity = 1); // Uninstall (remove) a symlink. // // This is essentially unistall_f() but with better low-verbosity // diagnostics. // static bool uninstall_l (const scope& rs, const install_dir& base, const path& link, const path& link_target, uint16_t verbosity = 1); // Uninstall (remove) an empty directory. // // uninstall -d // // We try to remove all the directories between base and dir but not // base itself unless base == dir. Return false if nothing has been // removed (i.e., the directories do not exist or are not empty). // static bool uninstall_d (const scope& rs, const install_dir& base, const dir_path& dir, uint16_t verbosity = 1); target_state perform_install (action, const target&) const; target_state perform_uninstall (action, const target&) const; static const file_rule instance; file_rule () {} private: virtual recipe apply (action, target&) const override; // Dummy simple_rule override. }; class fsdir_rule: public simple_rule { public: virtual bool match (action, target&) const override; virtual recipe apply (action, target&) const override; fsdir_rule () {} static const fsdir_rule instance; }; } } #endif // LIBBUILD2_INSTALL_RULE_HXX