// file : build/bin/module.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #include #include #include #include #include #include #include #include using namespace std; namespace build { namespace bin { static obj_rule obj_; static lib_rule lib_; // Default config.bin.*.lib values. // static const strings exe_lib {"shared", "static"}; static const strings liba_lib {"static"}; static const strings libso_lib {"shared"}; extern "C" void bin_init (scope& r, scope& b, const location&, std::unique_ptr&, bool first) { tracer trace ("bin::init"); level5 ([&]{trace << "for " << b.out_path ();}); // Register target types. // { auto& tts (b.target_types); tts.insert (); tts.insert (); tts.insert (); tts.insert (); tts.insert (); tts.insert (); tts.insert (); } // Register rules. // { auto& rs (b.rules); rs.insert (perform_id, update_id, "bin", obj_); rs.insert (perform_id, clean_id, "bin", obj_); rs.insert (perform_id, update_id, "bin", lib_); rs.insert (perform_id, clean_id, "bin", lib_); // Configure members. // rs.insert (configure_id, update_id, "lib", lib_); //@@ Should we check if the install module was loaded // (by checking if install operation is registered // for this project)? If we do that, then install // will have to be loaded before bin. Perhaps we // should enforce loading of all operation-defining // modules before all others? // rs.insert (perform_id, install_id, "bin", lib_); } // Enter module variables. // if (first) { variable_pool.find ("config.bin.lib", string_type); variable_pool.find ("config.bin.exe.lib", strings_type); variable_pool.find ("config.bin.liba.lib", strings_type); variable_pool.find ("config.bin.libso.lib", strings_type); variable_pool.find ("bin.lib", string_type); variable_pool.find ("bin.exe.lib", strings_type); variable_pool.find ("bin.liba.lib", strings_type); variable_pool.find ("bin.libso.lib", strings_type); } // Configure. // using config::required; // The idea here is as follows: if we already have one of // the bin.* variables set, then we assume this is static // project configuration and don't bother setting the // corresponding config.bin.* variable. // //@@ Need to validate the values. Would be more efficient // to do it once on assignment than every time on query. // Custom var type? // // config.bin.lib // { value& v (b.assign ("bin.lib")); if (!v) v = required (r, "config.bin.lib", "both").first; } // config.bin.exe.lib // { value& v (b.assign ("bin.exe.lib")); if (!v) v = required (r, "config.bin.exe.lib", exe_lib).first; } // config.bin.liba.lib // { value& v (b.assign ("bin.liba.lib")); if (!v) v = required (r, "config.bin.liba.lib", liba_lib).first; } // config.bin.libso.lib // { value& v (b.assign ("bin.libso.lib")); if (!v) v = required (r, "config.bin.libso.lib", libso_lib).first; } // Configure "installability" of our target types. // install::path (b, dir_path ("bin")); // Install into install.bin. // Should shared libraries have executable bit? That depends on // who you ask. In Debian, for example, it should not unless, it // really is executable (i.e., has main()). On the other hand, on // some systems, this may be required in order for the dynamic // linker to be able to load the library. So, by default, we will // keep it executable, especially seeing that this is also the // behavior of autotools. At the same time, it is easy to override // this, for example: // // config.install.lib.mode=644 // // And a library that wants to override any such overrides (e.g., // because it does have main()) can do: // // libso{foo}: install.mode=755 // // Everyone is happy then? // install::path (b, dir_path ("lib")); // Install into install.lib. install::path (b, dir_path ("lib")); // Install into install.lib. install::mode (b, "644"); } } }