diff --git a/add_dependent_lib.cpp b/add_dependent_lib.cpp index 02beca2..bb1818a 100644 --- a/add_dependent_lib.cpp +++ b/add_dependent_lib.cpp @@ -202,6 +202,12 @@ void bcp_implementation::add_dependent_lib(const std::string& libname, const fs: { m_dependencies[fs::path("libs") / libname / "build"] = p; // set up dependency tree add_path(fs::path("libs") / libname / "build"); + //m_dependencies[fs::path("boost-build.jam")] = p; + //add_path(fs::path("boost-build.jam")); + m_dependencies[fs::path("Jamroot")] = p; + add_path(fs::path("Jamroot")); + //m_dependencies[fs::path("tools/build")] = p; + //add_path(fs::path("tools/build")); } } } diff --git a/add_path.cpp b/add_path.cpp index 4e1be94..179f7ba 100644 --- a/add_path.cpp +++ b/add_path.cpp @@ -23,7 +23,7 @@ void bcp_implementation::add_path(const fs::path& p) { fs::path normalized_path = p; - normalized_path.normalize(); + normalized_path.normalize(); if(fs::exists(m_boost_path / normalized_path)) { if(fs::is_directory(m_boost_path / normalized_path)) @@ -34,6 +34,7 @@ void bcp_implementation::add_path(const fs::path& p) else { std::cerr << "CAUTION: dependent file " << p.string() << " does not exist." << std::endl; + std::cerr << " Found while scanning file " << m_dependencies[p].string() << std::endl; } } @@ -102,6 +103,37 @@ void bcp_implementation::add_file(const fs::path& p) { add_file_dependencies(p, false); } + if(is_jam_file(p) && m_namespace_name.size() && ((std::distance(p.begin(), p.end()) < 3) || (*p.begin() != "tools") || (*++p.begin() != "build"))) + { + // + // We're doing a rename of namespaces and library names + // so scan for names of libraries: + // + static const boost::regex e( + "\\ i(view.begin(), view.end(), e, 1); + boost::regex_token_iterator j; + while(i != j) + { + m_lib_names.insert(*i); + ++i; + } + static const std::pair specials_library_names[] = { + std::pair("libs/python/build/Jamfile.v2", "boost_python"), + std::pair("libs/python/build/Jamfile.v2", "boost_python3"), + }; + + for(unsigned int n = 0; n < (sizeof(specials_library_names)/sizeof(specials_library_names[0])); ++n) + { + if(0 == compare_paths(specials_library_names[n].first, p)) + { + m_lib_names.insert(specials_library_names[n].second); + } + } + } // // if this is a html file, scan for dependencies: // @@ -128,6 +160,14 @@ void bcp_implementation::add_file(const fs::path& p) s.erase(s.size() - 1); } // + // Remove any target suffix: + // + std::string::size_type n = s.find('#'); + if(n != std::string::npos) + { + s.erase(n); + } + // // if the name starts with ./ remove it // or we'll get an error: if(s.compare(0, 2, "./") == 0) @@ -280,7 +320,7 @@ void bcp_implementation::add_file_dependencies(const fs::path& p, bool scanfile) // Now we need to scan for Boost.Preprocessor includes that // are included via preprocessor iteration: // - boost::regex ppfiles("^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+(?:BOOST_PP_FILENAME|BOOST_PP_ITERATION_PARAMS|BOOST_PP_INDIRECT_SELF)[^\\n]+?[\"<]([^\">]+)[\">]"); + static const boost::regex ppfiles("^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+(?:BOOST_PP_FILENAME|BOOST_PP_ITERATION_PARAMS|BOOST_PP_INDIRECT_SELF)[^\\n]+?[\"<]([^\">]+)[\">]"); i = boost::regex_token_iterator(view.begin(), view.end(), ppfiles, 1); while(i != j) { @@ -410,7 +450,7 @@ void bcp_implementation::add_file_dependencies(const fs::path& p, bool scanfile) "BOOST_PP_UPDATE_COUNTER()", }; - boost::regex indirect_includes("^[[:blank:]]*#[[:blank:]]*include[[:blank:]]+([^\"<][^\n]*?)[[:blank:]]*$"); + static const boost::regex indirect_includes("^[[:blank:]]*#[[:blank:]]*include[[:blank:]]+([^\"<][^\n]*?)[[:blank:]]*$"); i = boost::regex_token_iterator(view.begin(), view.end(), indirect_includes, 1); while(i != j) { diff --git a/bcp.hpp b/bcp.hpp index 41bb070..96b5df4 100644 --- a/bcp.hpp +++ b/bcp.hpp @@ -29,6 +29,8 @@ class bcp_application virtual void set_boost_path(const char* p) = 0; virtual void set_destination(const char* p) = 0; virtual void add_module(const char* p) = 0; + virtual void set_namespace(const char* name) = 0; + virtual void set_namespace_alias(bool) = 0; virtual int run() = 0; diff --git a/bcp.html b/bcp.html deleted file mode 100644 index f4c4897..0000000 --- a/bcp.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - bcp - - - - -

- - - - - - -
-

C++ Boost

-
-

The bcp utility

-
-

Boost.Regex Index

-
-

-
-

-

The bcp utility is a tool for extracting subsets of Boost, it's useful for - Boost authors who want to distribute their library separately from Boost, and - for Boost users who want to distribute a subset of Boost with their - application.

-

bcp can also report on which parts of Boost your code is dependent on, and what - licences are used by those dependencies.

-

Examples:

-
bcp scoped_ptr /foo
-

Copies boost/scoped_ptr.hpp and dependencies to /foo.

-
bcp boost/regex.hpp /foo
-

Copies boost/regex.hpp and all dependencies including the regex source code (in - libs/regex/src) and build files (in libs/regex/build) to /foo.  Does not - copy the regex documentation,  test, or example code.

-
bcp regex /foo
-

Copies the full regex lib (in libs/regex) including dependencies (such as the - boost.test source required by the regex test programs) to /foo.

-
bcp regex config build /foo
-

Copies the full regex lib (in libs/regex) plus the config lib (libs/config) and - the build system (tools/build) to /foo including all the dependencies.

-
bcp --scan --boost=/boost foo.cpp bar.cpp boost
-

Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and - copies those dependencies to the sub-directory boost.

-
bcp --report regex.hpp boost-regex-report.html
-

Creates a HTML report called boost-regex-report.html for the boost - module regex.hpp.  The report contains license information, - author details, and file dependencies.

-

Syntax:

-
bcp --list [options] module-list
-

Outputs a list of all the files in module-list including dependencies.

-
bcp [options] module-list output-path
-

Copies all the files found in module-list to output-path

-
bcp --report [options] module-list html-file
-

Outputs a html report file containing:

-
    -
  • - All the licenses in effect, plus the files using each license, and - the copyright holders using each license. -
  • - Any files with no recognizable license (please report these to the boost - mailing lists). -
  • - Any files with no recognizable copyright holders (please report these to the - boost mailing lists). -
  • - All the copyright holders and the files on which they hold copyright. -
  • - File dependency information - indicates the reason for the inclusion of any - particular file in the dependencies found.
-

Options:

-
--boost=path
-

Sets the location of the boost tree to path.  If this option is - not provided then the current path is assumed to be the root directory of the - Boost tree.

-
--scan
-

Treats the module list as a list of (probably non-boost) files to scan for - boost dependencies, the files listed in the module list are not copied (or - listed), only the boost files upon which they depend.

-
--svn
-

Only copy files under svn version control.

-
--unix-lines
-

Make sure that all copied files use Unix style line endings.

-

module-list: 

-

When the --scan option is not used then a list of boost files or library - names to copy, this can be:

-
    -
  1. - The name of a tool: for example "build" will find "tools/build". -
  2. - The name of a library: for example "regex". -
  3. - The title of a header: for example "scoped_ptr" will find - "boost/scoped_ptr.hpp". -
  4. - The name of a header: for example "scoped_ptr.hpp" will find - "boost/scoped_ptr.hpp". -
  5. - The name of a file: for example "boost/regex.hpp".
-

When the --scan option is used, then a list of (probably non-boost) files to - scan for boost dependencies, the files in the module list are not therefore - copied/listed.

-

output-path: -

-

The path to which files will be copied (this path must exist).

-

Dependencies

-

File dependencies are found as follows:

-
    -
  • - C++ source files are scanned for #includes, all #includes present in the boost - source tree will then be scanned for their dependencies and so on.
  • -
  • - C++ source files are associated with the name of a library, if that library has - source code (and possibly build data), then include that source in the - dependencies.
  • -
  • - C++ source files are checked for dependencies on Boost.test (for example to see - if they use cpp_main as an entry point).
  • -
  • - HTML files are scanned for immediate dependencies (images and style sheets, but - not links).
-

It should be noted that in practice bcp can produce a rather "fat" list of - dependencies, reasons for this include:

-
    -
  • - It searches for library names first, so using "regex" as a name will give you - everything in the libs/regex directory and everything that depends on.  - This can be a long list as all the regex test and example programs will get - scanned for their dependencies.  If you want a more minimal list, then try - using the names of the headers you are actually including, or use the --scan - option to scan your source code.
  • -
  • - If you include the header of a library with separate source, then you get that - libraries source and all it's dependencies.  This is deliberate and in - general those extra dependencies are needed.
  • -
  • - When you include a header, bcp doesn't know what compiler you're using, so it - follows all possible preprocessor paths. If you're distributing a subset of - Boost with you're application then that is what you want to have happen in - general.
-

The last point above can result in a substantial increase in the number of - headers found compared to most peoples expectations.  For example bcp - finds 274 header dependencies for boost/shared_ptr.hpp: by running bcp in - report mode we can see why all these headers have been found as dependencies:

-
    -
  • - All of the Config library headers get included (52 headers, would be - about 6 for one compiler only).
  • -
  • - A lot of MPL and type traits code that includes workarounds for broken - compilers that you may or may not need.  Tracing back through the code - shows that most of these aren't needed unless the user has - defined BOOST_SP_USE_QUICK_ALLOCATOR, however bcp isn't aware of whether - that preprocessor path will be taken or not, so the headers get included just - in case.  This adds about 48 headers (type traits), plus another 49 from - MPL.
  • -
  • - The Preprocessor library gets used heavily by MPL: this adds another 96 - headers.
  • -
  • - The Shared Pointer library contains a lot of platform specific code, split up - into around 22 headers: normally your compiler would need only a couple of - these files.
-

As you can see the number of dependencies found are much larger than those used - by any single compiler, however if you want to distribute a subset of Boost - that's usable in any configuration, by any compiler, on any platform then - that's exactly what you need.  If you want to figure out which Boost - headers are being used by your specific compiler then the best way to - find out is to prepocess the code and scan the output for boost header - includes.  You should be aware that the result will be very platform and - compiler specific, and may not contain all the headers needed if you so much as - change a compiler switch (for example turn on threading support).

-

-

-


-

-

-

Last revised $Date$

-

© Copyright John Maddock 2003-7

-

Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) -

- - - - - - - diff --git a/bcp_imp.cpp b/bcp_imp.cpp index f00f022..88dcbdd 100644 --- a/bcp_imp.cpp +++ b/bcp_imp.cpp @@ -18,7 +18,9 @@ #include bcp_implementation::bcp_implementation() - : m_list_mode(false), m_list_summary_mode(false), m_license_mode(false), m_cvs_mode(false), m_svn_mode(false), m_unix_lines(false), m_scan_mode(false), m_bsl_convert_mode(false), m_bsl_summary_mode(false) + : m_list_mode(false), m_list_summary_mode(false), m_license_mode(false), m_cvs_mode(false), + m_svn_mode(false), m_unix_lines(false), m_scan_mode(false), m_bsl_convert_mode(false), + m_bsl_summary_mode(false), m_namespace_alias(false) { } @@ -100,6 +102,16 @@ void bcp_implementation::add_module(const char* p) m_module_list.push_back(p); } +void bcp_implementation::set_namespace(const char* name) +{ + m_namespace_name = name; +} + +void bcp_implementation::set_namespace_alias(bool b) +{ + m_namespace_alias = b; +} + fs::path get_short_path(const fs::path& p) { // truncate path no more than "x/y": @@ -152,7 +164,7 @@ int bcp_implementation::run() fs::ifstream in(blanket_permission); std::string line; while (std::getline(in, line)) { - boost::regex e("([^(]+)\\("); + static const boost::regex e("([^(]+)\\("); boost::smatch result; if (boost::regex_search(line, result, e)) m_bsl_authors.insert(format_authors_name(result[1])); diff --git a/bcp_imp.hpp b/bcp_imp.hpp index 54b41b0..6ee0aff 100644 --- a/bcp_imp.hpp +++ b/bcp_imp.hpp @@ -46,6 +46,7 @@ class bcp_implementation ~bcp_implementation(); static bool is_source_file(const fs::path& p); static bool is_html_file(const fs::path& p); + static bool is_jam_file(const fs::path& p); private: // // the following are the overridden virtuals from the base class: @@ -62,6 +63,8 @@ class bcp_implementation void set_boost_path(const char* p); void set_destination(const char* p); void add_module(const char* p); + void set_namespace(const char* name); + void set_namespace_alias(bool); virtual int run(); @@ -90,18 +93,22 @@ class bcp_implementation bool m_scan_mode; // scan non-boost files. bool m_bsl_convert_mode; // try to convert to the BSL bool m_bsl_summary_mode; // summarise BSL issues only + bool m_namespace_alias; // make "boost" a namespace alias when doing a namespace rename. fs::path m_boost_path; // the path to the boost root fs::path m_dest_path; // the path to copy to - std::map m_cvs_paths; // valid files under cvs control - std::set m_copy_paths; // list of files to copy - std::map m_license_data; // licenses in use - std::set m_unknown_licenses; // files with no known license - std::set m_unknown_authors; // files with no known copyright/author - std::set m_can_migrate_to_bsl; // files that can migrate to the BSL - std::set m_cannot_migrate_to_bsl; // files that cannot migrate to the BSL - std::set m_bsl_authors; // authors giving blanket permission to use the BSL - std::set m_authors_for_bsl_migration; // authors we need for BSL migration - std::map, path_less> m_converted_to_bsl; - std::map > m_author_data; // all the authors - std::map m_dependencies; // dependency information + std::map m_cvs_paths; // valid files under cvs control + std::set m_copy_paths; // list of files to copy + std::map m_license_data; // licenses in use + std::set m_unknown_licenses; // files with no known license + std::set m_unknown_authors; // files with no known copyright/author + std::set m_can_migrate_to_bsl; // files that can migrate to the BSL + std::set m_cannot_migrate_to_bsl; // files that cannot migrate to the BSL + std::set m_bsl_authors; // authors giving blanket permission to use the BSL + std::set m_authors_for_bsl_migration; // authors we need for BSL migration + std::map, path_less> + m_converted_to_bsl; + std::map > m_author_data; // all the authors + std::map m_dependencies; // dependency information + std::string m_namespace_name; // namespace rename. + std::set m_lib_names; // List of library binary names }; diff --git a/copy_path.cpp b/copy_path.cpp index c976865..860248a 100644 --- a/copy_path.cpp +++ b/copy_path.cpp @@ -11,12 +11,36 @@ */ #include "bcp_imp.hpp" +#include "fileview.hpp" #include +#include #include #include #include #include +struct get_new_library_name +{ + get_new_library_name(const std::string& n) : m_new_name(n) {} + template + std::string operator()(const boost::match_results& what) + { + std::string s = what[0]; + std::string::size_type n = s.find("boost"); + if(n == std::string::npos) + { + s.insert(0, m_new_name); + } + else + { + s.replace(n, 5, m_new_name); + } + return s; + } +private: + std::string m_new_name; +}; + void bcp_implementation::copy_path(const fs::path& p) { assert(!fs::is_directory(m_boost_path / p)); @@ -34,7 +58,115 @@ void bcp_implementation::copy_path(const fs::path& p) // // do text based copy if requested: // - if(m_unix_lines && !is_binary_file(p)) + if(m_namespace_name.size() && m_lib_names.size() && is_jam_file(p)) + { + static std::vector v1, v2; + v1.clear(); + v2.clear(); + std::ifstream is((m_boost_path / p).native_file_string().c_str()); + std::copy(std::istreambuf_iterator(is), std::istreambuf_iterator(), std::back_inserter(v1)); + + static boost::regex libname_matcher; + if(libname_matcher.empty()) + { + std::string re = "\\<"; + re += *m_lib_names.begin(); + for(std::set::const_iterator i = ++m_lib_names.begin(); i != m_lib_names.end(); ++i) + { + re += "|" + *i; + } + re += "\\>"; + libname_matcher.assign(re); + } + + regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, get_new_library_name(m_namespace_name)); + std::swap(v1, v2); + v2.clear(); + + std::ofstream os; + if(m_unix_lines) + os.open((m_dest_path / p).native_file_string().c_str(), std::ios_base::binary | std::ios_base::out); + else + os.open((m_dest_path / p).native_file_string().c_str(), std::ios_base::out); + os.write(&*v1.begin(), v1.size()); + os.close(); + } + else if(m_namespace_name.size() && is_source_file(p)) + { + // + // v1 hold the current content, v2 is temp buffer. + // Each time we do a search and replace the new content + // ends up in v2: we then swap v1 and v2, and clear v2. + // + static std::vector v1, v2; + v1.clear(); + v2.clear(); + std::ifstream is((m_boost_path / p).native_file_string().c_str()); + std::copy(std::istreambuf_iterator(is), std::istreambuf_iterator(), std::back_inserter(v1)); + + static const boost::regex namespace_matcher( + "(?|" + "(namespace\\s+)boost\\>()" + "|" + "()boost(\\s*(?:::|,|\\)))" + "|" + "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?)boost\\>()" + "|" + "(^\\s*#\\s*define[^\\n]+)boost(\\s*)$" + ")" + ); + + regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_matcher, "$1" + m_namespace_name + "$2"); + std::swap(v1, v2); + v2.clear(); + + if(m_namespace_alias) + { + static const boost::regex namespace_alias( + /* + "namespace\\s+" + m_namespace_name + + "\\s*" + "(" + "\\{" + "(?:" + "(?>[^\\{\\}/]+)" + "(?>" + "(?:" + "(?1)" + "|//[^\\n]+$" + "|/[^/]" + "|(?:^\\s*#[^\\n]*" + "(?:(?<=\\\\)\\n[^\\n]*)*)" + ")" + "[^\\{\\}]+" + ")*" + ")*" + "\\}" + ")" + */ + /* + "(namespace\\s+" + m_namespace_name + + "\\s*\\{.*" + "\\})([^\\{\\};]*)\\z" + */ + "namespace\\s+" + m_namespace_name + + "\\s*\\{" + ); + regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_alias, + "namespace " + m_namespace_name + "{} namespace boost = " + m_namespace_name + "; namespace " + m_namespace_name + "{"); + std::swap(v1, v2); + v2.clear(); + } + + std::ofstream os; + if(m_unix_lines) + os.open((m_dest_path / p).native_file_string().c_str(), std::ios_base::binary | std::ios_base::out); + else + os.open((m_dest_path / p).native_file_string().c_str(), std::ios_base::out); + os.write(&*v1.begin(), v1.size()); + os.close(); + } + else if(m_unix_lines && !is_binary_file(p)) { std::ifstream is((m_boost_path / p).native_file_string().c_str()); std::istreambuf_iterator isi(is); diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..9bc5092 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,22 @@ + +# Copyright John Maddock 2005. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using quickbook ; + +xml bcp : bcp.qbk ; +boostbook standalone + : + bcp + : + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=0 + # Path for links to Boost: + boost.root=../../../.. + # Path for libraries index: + boost.libraries=../../../../libs/libraries.htm + # Use the main Boost stylesheet: + html.stylesheet=../../../../doc/html/boostbook.css + ; + diff --git a/doc/bcp.qbk b/doc/bcp.qbk new file mode 100644 index 0000000..d1046dc --- /dev/null +++ b/doc/bcp.qbk @@ -0,0 +1,209 @@ + +[article BCP + [quickbook 1.4] + [copyright 2209 John Maddock] + [purpose Regular Expressions] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Maddock, John]] + [category text] + [/last-revision $Date: 2008-02-21 12:58:15 +0000 (Thu, 21 Feb 2008) $] +] + +[section:overview Overview] + +The bcp utility is a tool for extracting subsets of Boost, it's useful for Boost authors who want to distribute +their library separately from Boost, and for Boost users who want to distribute a subset of Boost with their application. + +bcp can also report on which parts of Boost your code is dependent on, and what licences are used by those dependencies. + +[endsect] + +[section:examples Examples] + +[pre +bcp scoped_ptr /foo +] + +Copies boost/scoped_ptr.hpp and dependencies to /foo. + +[pre +bcp boost/regex.hpp /foo +] + +Copies boost/regex.hpp and all dependencies including the regex source code (in libs/regex/src) and +build files (in libs/regex/build) to /foo. Does not copy the regex documentation, test, or example code. + +[pre +bcp regex /foo +] + +Copies the full regex lib (in libs/regex) including dependencies (such as the boost.test source required +by the regex test programs) to /foo. + +[pre +bcp --namespace=myboost --namespace-alias regex config build /foo +] + +Copies the full regex lib (in libs\/regex) plus the config lib (libs\/config) and the build system (tools\/build) +to \/foo including all the dependencies. Also renames the boost namespace to /myboost/ and changes the filenames +of binary libraries to begin with the prefix "myboost" rather than "boost". The --namespace-alias option makes +`namespace boost` an alias of the new name. + +[pre +bcp --scan --boost=/boost foo.cpp bar.cpp boost +] + +Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and copies those dependencies to the sub-directory boost. + +[pre +bcp --report regex.hpp boost-regex-report.html +] + +Creates a HTML report called boost-regex-report.html for the boost module regex.hpp. The report contains license information, author details, and file dependencies. + +[endsect] + +[section:syntax Syntax] + +[section:main Behaviour Selection] + +[pre +bcp --list \[options\] module-list +] + +Outputs a list of all the files in module-list including dependencies. + +[pre +bcp \[options\] module-list output-path +] + +Copies all the files found in module-list to output-path + +[pre +bcp --report \[options\] module-list html-file +] + +Outputs a html report file containing: + +* All the licenses in effect, plus the files using each license, and the copyright holders using each license. +* Any files with no recognizable license (please report these to the boost mailing lists). +* Any files with no recognizable copyright holders (please report these to the boost mailing lists). +* All the copyright holders and the files on which they hold copyright. +* File dependency information - indicates the reason for the inclusion of any particular file in the dependencies found. + +[endsect] + +[section:options Options] + +[pre +--boost=path +] + +Sets the location of the boost tree to path. If this option is not provided then the current path is assumed to be +the root directory of the Boost tree. + +[pre --namespace=newname ] + +When copying files, all occurances of the boost namespace will get renamed to "newname". Also +renames Boost binaries to use "newname" rather than "boost" as a prefix. + +Often used in conjunction with the --namespace-alias option, this allows two different Boost versions to be +used in the same program, but not in the same translation unit. + +[pre --namespace-alias] + +When used in conjunction with the --namespace option, then `namespace boost` will be declared as an alias +of the new namespace name. This allows existing code that relies on Boost code being in `namespace boost` +to compile unchanged, while retaining the "strong versioning" that can be achieved with a namespace change. + +[pre +--scan +] + +Treats the module list as a list of (probably non-boost) files to scan for boost dependencies, +the files listed in the module list are not copied (or listed), only the boost files upon which they depend. + +[pre +--svn +] + +Only copy files under svn version control. + +[pre +--unix-lines +] + +Make sure that all copied files use Unix style line endings. + +[endsect] + +[section:module module-list] + +When the --scan option is not used then a list of boost files or library names to copy, this can be: + +# The name of a tool: for example "build" will find "tools/build". +# The name of a library: for example "regex". +# The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp". +# The name of a header: for example "scoped_ptr.hpp" will find "boost/scoped_ptr.hpp". +# The name of a file: for example "boost/regex.hpp". + +When the --scan option is used, then a list of (probably non-boost) files to scan for boost dependencies, +the files in the module list are not therefore copied/listed. + +[endsect] + +[section:output output-path] + +The path to which files will be copied (this path must exist). + +[endsect] + +[section Dependencies] + +File dependencies are found as follows: + +* C++ source files are scanned for #includes, all #includes present in the boost source tree will then be scanned for +their dependencies and so on. +* C++ source files are associated with the name of a library, if that library has source code +(and possibly build data), then include that source in the dependencies. +* C++ source files are checked for dependencies on Boost.test (for example to see if they use cpp_main as an entry point). +* HTML files are scanned for immediate dependencies (images and style sheets, but not links). + +It should be noted that in practice bcp can produce a rather "fat" list of dependencies, reasons for this include: +* It searches for library names first, so using "regex" as a name will give you everything in the +libs/regex directory and everything that depends on. This can be a long list as all the regex test and example +programs will get scanned for their dependencies. If you want a more minimal list, then try using the +names of the headers you are actually including, or use the --scan option to scan your source code. +* If you include the header of a library with separate source, then you get that libraries source and all +it's dependencies. This is deliberate and in general those extra dependencies are needed. +* When you include a header, bcp doesn't know what compiler you're using, so it follows all +possible preprocessor paths. If you're distributing a subset of Boost with you're application then that +is what you want to have happen in general. + +The last point above can result in a substantial increase in the number of headers found compared to most +peoples expectations. For example bcp finds 274 header dependencies for boost/shared_ptr.hpp: by +running bcp in report mode we can see why all these headers have been found as dependencies: + +* All of the Config library headers get included (52 headers, would be about 6 for one compiler only). +* A lot of MPL and type traits code that includes workarounds for broken compilers that you may or may not need. +Tracing back through the code shows that most of these aren't needed unless the user has +defined BOOST_SP_USE_QUICK_ALLOCATOR, however bcp isn't aware of whether that preprocessor path will be +taken or not, so the headers get included just in case. This adds about 48 headers (type traits), plus another 49 from MPL. +* The Preprocessor library gets used heavily by MPL: this adds another 96 headers. +* The Shared Pointer library contains a lot of platform specific code, split up into around 22 headers: +normally your compiler would need only a couple of these files. + +As you can see the number of dependencies found are much larger than those used by any single compiler, +however if you want to distribute a subset of Boost that's usable in any configuration, by any compiler, +on any platform then that's exactly what you need. If you want to figure out which Boost headers are +being used by your specific compiler then the best way to find out is to prepocess the code and scan +the output for boost header includes. You should be aware that the result will be very platform and compiler +specific, and may not contain all the headers needed if you so much as change a compiler switch +(for example turn on threading support). + +[endsect] +[endsect] diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..d80c940 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,344 @@ + + + +BCP + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+
+
+
+

+BCP

+

+John Maddock +

+
+
+

+ Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

+
+
+
+
+ +
+ +

+ The bcp utility is a tool for extracting subsets of Boost, it's useful for + Boost authors who want to distribute their library separately from Boost, and + for Boost users who want to distribute a subset of Boost with their application. +

+

+ bcp can also report on which parts of Boost your code is dependent on, and + what licences are used by those dependencies. +

+
+
+ +
bcp scoped_ptr /foo
+
+

+ Copies boost/scoped_ptr.hpp and dependencies to /foo. +

+
bcp boost/regex.hpp /foo
+
+

+ Copies boost/regex.hpp and all dependencies including the regex source code + (in libs/regex/src) and build files (in libs/regex/build) to /foo. Does not + copy the regex documentation, test, or example code. +

+
bcp regex /foo
+
+

+ Copies the full regex lib (in libs/regex) including dependencies (such as the + boost.test source required by the regex test programs) to /foo. +

+
bcp --namespace=myboost --namespace-alias regex config build /foo
+
+

+ Copies the full regex lib (in libs/regex) plus the config lib (libs/config) + and the build system (tools/build) to /foo including all the dependencies. + Also renames the boost namespace to myboost and changes + the filenames of binary libraries to begin with the prefix "myboost" + rather than "boost". The --namespace-alias option makes namespace boost + an alias of the new name. +

+
bcp --scan --boost=/boost foo.cpp bar.cpp boost
+
+

+ Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and + copies those dependencies to the sub-directory boost. +

+
bcp --report regex.hpp boost-regex-report.html
+
+

+ Creates a HTML report called boost-regex-report.html for the boost module regex.hpp. + The report contains license information, author details, and file dependencies. +

+
+
+ + +
+ +
bcp --list [options] module-list
+
+

+ Outputs a list of all the files in module-list including dependencies. +

+
bcp [options] module-list output-path
+
+

+ Copies all the files found in module-list to output-path +

+
bcp --report [options] module-list html-file
+
+

+ Outputs a html report file containing: +

+
    +
  • + All the licenses in effect, plus the files using each license, and the + copyright holders using each license. +
  • +
  • + Any files with no recognizable license (please report these to the boost + mailing lists). +
  • +
  • + Any files with no recognizable copyright holders (please report these to + the boost mailing lists). +
  • +
  • + All the copyright holders and the files on which they hold copyright. +
  • +
  • + File dependency information - indicates the reason for the inclusion of + any particular file in the dependencies found. +
  • +
+
+
+ +
--boost=path
+
+

+ Sets the location of the boost tree to path. If this option is not provided + then the current path is assumed to be the root directory of the Boost tree. +

+
--namespace=newname 
+

+ When copying files, all occurances of the boost namespace will get renamed + to "newname". Also renames Boost binaries to use "newname" + rather than "boost" as a prefix. +

+

+ Often used in conjunction with the --namespace-alias option, this allows + two different Boost versions to be used in the same program, but not in the + same translation unit. +

+
--namespace-alias
+

+ When used in conjunction with the --namespace option, then namespace boost + will be declared as an alias of the new namespace name. This allows existing + code that relies on Boost code being in namespace + boost to compile unchanged, while + retaining the "strong versioning" that can be achieved with a namespace + change. +

+
--scan
+
+

+ Treats the module list as a list of (probably non-boost) files to scan for + boost dependencies, the files listed in the module list are not copied (or + listed), only the boost files upon which they depend. +

+
--svn
+
+

+ Only copy files under svn version control. +

+
--unix-lines
+
+

+ Make sure that all copied files use Unix style line endings. +

+
+
+ +

+ When the --scan option is not used then a list of boost files or library + names to copy, this can be: +

+
    +
  1. + The name of a tool: for example "build" will find "tools/build". +
  2. +
  3. + The name of a library: for example "regex". +
  4. +
  5. + The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp". +
  6. +
  7. + The name of a header: for example "scoped_ptr.hpp" will find + "boost/scoped_ptr.hpp". +
  8. +
  9. + The name of a file: for example "boost/regex.hpp". +
  10. +
+

+ When the --scan option is used, then a list of (probably non-boost) files + to scan for boost dependencies, the files in the module list are not therefore + copied/listed. +

+
+
+ +

+ The path to which files will be copied (this path must exist). +

+
+
+ +

+ File dependencies are found as follows: +

+
    +
  • + C++ source files are scanned for #includes, all #includes present in the + boost source tree will then be scanned for their dependencies and so on. +
  • +
  • + C++ source files are associated with the name of a library, if that library + has source code (and possibly build data), then include that source in + the dependencies. +
  • +
  • + C++ source files are checked for dependencies on Boost.test (for example + to see if they use cpp_main as an entry point). +
  • +
  • + HTML files are scanned for immediate dependencies (images and style sheets, + but not links). +
  • +
+

+ It should be noted that in practice bcp can produce a rather "fat" + list of dependencies, reasons for this include: * It searches for library + names first, so using "regex" as a name will give you everything + in the libs/regex directory and everything that depends on. This can be a + long list as all the regex test and example programs will get scanned for + their dependencies. If you want a more minimal list, then try using the names + of the headers you are actually including, or use the --scan option to scan + your source code. * If you include the header of a library with separate + source, then you get that libraries source and all it's dependencies. This + is deliberate and in general those extra dependencies are needed. * When + you include a header, bcp doesn't know what compiler you're using, so it + follows all possible preprocessor paths. If you're distributing a subset + of Boost with you're application then that is what you want to have happen + in general. +

+

+ The last point above can result in a substantial increase in the number of + headers found compared to most peoples expectations. For example bcp finds + 274 header dependencies for boost/shared_ptr.hpp: by running bcp in report + mode we can see why all these headers have been found as dependencies: +

+
    +
  • + All of the Config library headers get included (52 headers, would be about + 6 for one compiler only). +
  • +
  • + A lot of MPL and type traits code that includes workarounds for broken + compilers that you may or may not need. Tracing back through the code shows + that most of these aren't needed unless the user has defined BOOST_SP_USE_QUICK_ALLOCATOR, + however bcp isn't aware of whether that preprocessor path will be taken + or not, so the headers get included just in case. This adds about 48 headers + (type traits), plus another 49 from MPL. +
  • +
  • + The Preprocessor library gets used heavily by MPL: this adds another 96 + headers. +
  • +
  • + The Shared Pointer library contains a lot of platform specific code, split + up into around 22 headers: normally your compiler would need only a couple + of these files. +
  • +
+

+ As you can see the number of dependencies found are much larger than those + used by any single compiler, however if you want to distribute a subset of + Boost that's usable in any configuration, by any compiler, on any platform + then that's exactly what you need. If you want to figure out which Boost + headers are being used by your specific compiler then the best way to find + out is to prepocess the code and scan the output for boost header includes. + You should be aware that the result will be very platform and compiler specific, + and may not contain all the headers needed if you so much as change a compiler + switch (for example turn on threading support). +

+
+
+
+ + + +

Last revised: December 28, 2009 at 13:24:19 GMT

+
+
+ + diff --git a/file_types.cpp b/file_types.cpp index bc9ca31..abc0149 100644 --- a/file_types.cpp +++ b/file_types.cpp @@ -19,11 +19,11 @@ bool bcp_implementation::is_source_file(const fs::path& p) static const boost::regex e( ".*\\." "(?:" - "c|cxx|h|hxx|inc|.?pp|yy?" + "c|cxx|h|hxx|inc|inl|.?pp|yy?" ")", boost::regex::perl | boost::regex::icase ); - return boost::regex_match(p.string(), e); + return boost::regex_match(p.filename(), e); } bool bcp_implementation::is_html_file(const fs::path& p) @@ -34,7 +34,7 @@ bool bcp_implementation::is_html_file(const fs::path& p) "html?|css" ")" ); - return boost::regex_match(p.string(), e); + return boost::regex_match(p.filename(), e); } bool bcp_implementation::is_binary_file(const fs::path& p) @@ -55,3 +55,18 @@ bool bcp_implementation::is_binary_file(const fs::path& p) return !boost::regex_match(p.leaf(), e); } + +bool bcp_implementation::is_jam_file(const fs::path& p) +{ + static const boost::regex e( + ".*\\." + "(?:" + "jam|v2" + ")" + "|" + "(Jamfile|Jamroot)\\.?", + boost::regex::perl | boost::regex::icase + ); + return boost::regex_match(p.filename(), e); +} + diff --git a/index.html b/index.html index 6e28ef8..34e938c 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - +

- Automatic redirection failed, please go to bcp.html. + Automatic redirection failed, please go to doc/html/index.html.

Copyright John Maddock 2007

Distributed under the Boost Software License, Version 1.0. (See accompanying file diff --git a/main.cpp b/main.cpp index a07991c..5c29c73 100644 --- a/main.cpp +++ b/main.cpp @@ -34,15 +34,17 @@ void show_usage() " bcp [options] module-list output-path\n" "\n" "Options:\n" - " --boost=path sets the location of the boost tree to path\n" - " --scan treat the module list as a list of (possibly non-boost)\n" - " files to scan for boost dependencies\n" - " --cvs only copy files under cvs version control\n" - " --unix-lines make sure that all copied files use Unix style line endings\n" + " --boost=path sets the location of the boost tree to path\n" + " --scan treat the module list as a list of (possibly non-boost)\n" + " files to scan for boost dependencies\n" + " --svn only copy files under cvs version control\n" + " --unix-lines make sure that all copied files use Unix style line endings\n" + " --namespace=name rename the boost namespace to name (also changes library names).\n" + " --namespace-alias Makes namespace boost an alias of the namespace set with --namespace.\n" "\n" - "module-list: a list of boost files or library names to copy\n" - "html-file: the name of a html file to which the report will be written\n" - "output-path: the path to which files will be copied\n"; + "module-list: a list of boost files or library names to copy\n" + "html-file: the name of a html file to which the report will be written\n" + "output-path: the path to which files will be copied\n"; } bool filesystem_name_check( const std::string & name ) @@ -135,6 +137,14 @@ int cpp_main(int argc, char* argv[]) { papp->set_boost_path(argv[i] + 8); } + else if(0 == std::strncmp("--namespace=", argv[i], 12)) + { + papp->set_namespace(argv[i] + 12); + } + else if(0 == std::strncmp("--namespace-alias", argv[i], 17)) + { + papp->set_namespace_alias(true); + } else if(argv[i][0] == '-') { std::cout << "Error: Unknown argument " << argv[i] << std::endl; diff --git a/output_licence_info.cpp b/output_licence_info.cpp index 2196894..26eae7b 100644 --- a/output_licence_info.cpp +++ b/output_licence_info.cpp @@ -139,7 +139,7 @@ void bcp_implementation::output_license_info() // version): // fileview version_file(m_boost_path / "boost/version.hpp"); - boost::regex version_regex( + static const boost::regex version_regex( "^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+BOOST_VERSION[[:blank:]]+(\\d+)"); boost::cmatch what; if(boost::regex_search(version_file.begin(), version_file.end(), what, version_regex))