配置SublimeText为Boost开发环境

Recently, I would like to study the Boost library. Most tutorials available online are based on using IDEs (such as VS/Code::Blocks), but I find it frustrating to have to open a bloated IDE just to write some test code. Today, I fiddled around and managed to compile/link code that uses the Boost library in SublimeText. I also organized the process/tools I worked with, so if others have similar needs and happen to see this article, they can save some time.

2016.11.01 Update
I used the latest version of MinGW64-GCC6.2 (x86_64-6.2.0-posix-seh-rt_v5-rev1) to compile LLVM/Clang 3.9, and then I used the compiled Clang to compile Boost1.62. The error messages that occurred when linking the Boost library in Clang are gone now.
Note: When compiling Boost with Clang, it is best to ensure that the current version of clang is compiled from the version of gcc in the current system; otherwise, when linking the static libraries produced by clang, strange issues might arise.

You can download my compiled versions here: MinGW62-GCC6.2(x86_64-6.2.0-posix-seh-rt_v5-rev1), LLVM/Clang3.9 compiled with GCC6.2 (above MinGW version), and Boost(MinGW64-GCC6.2/LLVM3.9/VC14-ALL). You can choose the version of the linked library (debug/release/static, etc.) as needed.
You can download the full compilation toolchain here.

Original Article
First, make sure that you have LLVM(clang) + GCC(MinGW)/MSVC installed on your computer (this article only writes about Clang/GCC versions)—or download my C++ toolchain (Cmake/Mingw/LLVM/Cppcheck) and add it to your system’s PATH.

I am using GCC version 6.2.0 (x86_64-posix-seh-rev1) and LLVM (Clang 3.9) version is x86_64-w64-windows-gnu (Thread model: posix).

Then, download the latest version from boost.org source code / installer.

Assuming you downloaded the source version in the previous step, after extracting it locally, there will be a bootstrap.bat file in its directory. Executing it will automatically compile b2.exe and bjam.exe.

Then start compilation (using Clang/GCC/MSVC14). Here I choose to use clang:

1
2
3
4
5
6
# Clang compilation
$ bjam stage --toolset=clang --stagedir="D:\boost\clang" link=static runtime-link=shared runtime-link=static threading=multi debug release
# GCC compilation
$ bjam stage --toolset=gcc --stagedir="D:\boost\mingw" link=static runtime-link=shared runtime-link=static threading=multi debug release
# MSVC2015 compilation
$ bjam stage --toolset=msvc-14.0 address-model=64 --stagedir="D:\boost\vc14" link=static runtime-link=shared runtime-link=static threading=multi debug release
  • --toolset indicates the toolset used for compiling Boost.
  • address-model=64: This parameter follows --toolset; it indicates whether the compiled version is 32-bit or 64-bit. If not specified while using VS, it defaults to 32-bit.
  • --stagedir: Specifies the directory where the compiled results will be stored.
  • --link: Indicates the type of linked library; static means static library, while shared means dynamic library.
  • --runtime-link: Specifies the runtime linking approach; static indicates static linkage with C/C++ runtime (/MT and /MTd), while shared denotes dynamic linkage with C/C++ runtime (/MD and /MDd), mixing linked libraries can cause LNK2038 error.
  • --threading: Specifies whether to use a multi-threaded or single-threaded library; multi for multi-threading, single for single-threading.
  • --address-model: Indicates whether to compile for 64-bit or 32-bit.
  • --stage: Indicates only to generate dll or lib, without generating a header file directory containing the include directory. If you need to generate an include directory with header files, use the install parameter.
  • debug/release: Generates debug or release versions.

Note: The version of Boost compiled by clang and gcc (x86/x64) depends on your compiler version (x86/x64), while the default for MSVC is x86. Therefore, using the above default compilation scheme, it’s not possible to compile x64-debug or x64-release in VS. The solution is to specify compiling for the x64 version of Boost while compiling: address-model=64.

Using any of the above will compile four versions of the lib: (multiThread-Release/multiThread-Debug/multiThread-StaticLink-Release/multiThread-StaticLink-Debug). You can download the three versions I compiled (clang/gcc/msvc) here.
It takes about tens of minutes for the compilation to complete, and afterward a Boost folder will be generated in the D drive root directory.

From the compilation parameters, we can see the generated lib and corresponding versions:

  1. Those starting with “lib” are the “link-static” version, while those directly starting with “boost” are the “link-shared” version.
  2. Versions containing “d” are debug versions, while those not containing “d” are release versions.
  3. Versions containing “s” are the “runtime-link-static” version; those without are “runtime-link-shared” versions.
  4. Versions containing “mt” are “threading-multi” versions; those without are “threading-single” versions.

For example:

1
2
3
4
5
6
7
8
9
10
11
# Using this command will produce four files
$ bjam stage --toolset=msvc-14.0 address-model=64 --stagedir="D:\boost\vc14" link=static runtime-link=shared runtime-link=static threading=multi debug release

# Multi-threaded (mt)/MT Release version (no d)
libboost_system-vc140-mt-s-1_62.lib
# Multi-threaded (mt)/MD Release version (no d)
libboost_system-vc140-mt-1_62.lib
# Multi-threaded (mt)/MT Debug version (with d)
libboost_system-vc140-mt-sgd-1_62.lib
# Multi-threaded (mt)/MD Debug version
libboost_system-vc140-mt-gd-1_62.lib

Copy /boost from the Boost source into LLVM/include/, and copy the files from the compiled D:/Boost/lib into LLVM/lib (or you can add the directory where the Boost source (/Boost/boost) and lib (/Boost/lib) are located to your system’s PATH, similar below).

OK, at this point, Boost is installed on your computer. If you need to customize modules, there are many tutorials online about how to compile and install Boost—just search for them.

However, compilation and linking can still be a significant issue. Many tutorials use IDEs to write Boost code, but as someone who prefers a lightweight environment, I dislike bloated IDEs, so I have to manually write the compilation and linking commands.

Let’s first test the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// printDirC.cc
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
/**
* Outputs the names of all files and directories in the current directory
*/
int main()
{
// Get current directory
fs::path full_path(fs::current_path());
fs::directory_iterator end_iter;
for (fs::directory_iterator dir_itr(full_path); dir_itr != end_iter; ++dir_itr )
{
std::cout << dir_itr->path().filename() << std::endl;
}
}

The command to compile this code using clang++ is:

1
$ clang++ -o boost.exe boost.cc -I"C:\Program Files\BuildPath\LLVM\include" -static -L"C:\Program Files\BuildPath\LLVM\lib"

Additionally, since the code above uses boost_filesystem, we need to link the boost_filesystem library during compilation. Since boost_filesystem depends on boost_system, we must also include boost_system in the linking options.

1
$ g++ -o printDirC.exe printDirC.cc -I"C:\Program Files\BuildPath\LLVM\include" -L"C:\Program Files\BuildPath\LLVM\lib" -libboost_system-clang39-mt-s-1_62 -libboost_filesystem-clang39-mt-s-1_62

Many articles online say to use -lboost_system, but the names are not like that for the versions compiled with clang in Boost1.62.0, rather they are libboost_system-clang39-mt-s-1_62.lib (for gcc it’s libboost_system-mgw62-mt-s-1_62.a), and examples alike.

MinGW automatically adds the prefix lib and .a extensions when linking static libraries, while clang will only automatically add the .a extension and look for the corresponding library files in available paths.

For instance, when we write -llibboost_system-clang39-mt-s-1_62, it would locate libboost_system-clang39-mt-s-1_62.lib (for gcc-compiled version it is written as -lboost_system-mgw62-mt-s-1_62, it would find libboost_system-mgw62-mt-s-1_62.lib).

Thus, to link to the library, the library parameter (for GCC version) should be the static library file with the prefix lib and file suffix removed, and for the Clang version, it should be the file suffix removed.

The libraries in Boost that we can link to and the compilation linking parameters are as follows (here clang39 and 1_62 stand for the compiler and Boost version; I am only listing the multi-threaded static-link release version of lib):

Library clang version linking parameter GCC version linking parameter
boost_atomic -llibboost_atomic-clang39-mt-s-1_62 -lboost_atomic-mgw62-mt-s-1_62
boost_chrono -llibboost_chrono-clang39-mt-s-1_62 -lboost_chrono-mgw62-mt-s-1_62
boost_container -llibboost_container-clang39-mt-s-1_62 -lboost_container-mgw62-mt-s-1_62
boost_context -lboost_context-mgw62-mt-s-1_62
boost_coroutine -lboost_coroutine-mgw62-mt-s-1_62
boost_date_time -llibboost_date_time-clang39-mt-s-1_62 -lboost_date_time-mgw62-mt-s-1_62
boost_exception -llibboost_exception-clang39-mt-s-1_62 -lboost_exception-mgw62-mt-s-1_62
boost_filesystem -llibboost_filesystem-clang39-mt-s-1_62 -lboost_filesystem-mgw62-mt-s-1_62
boost_graph -llibboost_graph-clang39-mt-s-1_62 -lboost_graph-mgw62-mt-s-1_62
boost_iostreams -llibboost_iostreams-clang39-mt-s-1_62 -lboost_iostreams-mgw62-mt-s-1_62
boost_locale -lboost_locale-mgw62-mt-s-1_62
boost_log_setup -llibboost_log_setup-clang39-mt-s-1_62 -lboost_log_setup-mgw62-mt-s-1_62
boost_log -llibboost_log-clang39-mt-s-1_62 -lboost_log-mgw62-mt-s-1_62
boost_math_c99f -llibboost_math_c99f-clang39-mt-s-1_62 -lboost_math_c99f-mgw62-mt-s-1_62
boost_math_c99l -llibboost_math_c99l-clang39-mt-s-1_62 -lboost_math_c99l-mgw62-mt-s-1_62
boost_math_c99 -llibboost_math_c99-clang39-mt-s-1_62 -lboost_math_c99-mgw62-mt-s-1_62
boost_math_tr1f -llibboost_math_tr1f-clang39-mt-s-1_62 -lboost_math_tr1f-mgw62-mt-s-1_62
boost_math_tr1l -llibboost_math_tr1l-clang39-mt-s-1_62 -lboost_math_tr1l-mgw62-mt-s-1_62
boost_math_tr1 -llibboost_math_tr1-clang39-mt-s-1_62 -lboost_math_tr1-mgw62-mt-s-1_62
boost_prg_exec_monitor -llibboost_prg_exec_monitor-clang39-mt-s-1_62 -lboost_prg_exec_monitor-mgw62-mt-s-1_62
boost_program_options -llibboost_program_options-clang39-mt-s-1_62 -lboost_program_options-mgw62-mt-s-1_62
boost_python3 -llibboost_python-clang39-mt-s-1_62
boost_python -llibboost_python-clang39-mt-s-1_62
boost_random -llibboost_random-clang39-mt-s-1_62 -lboost_random-mgw62-mt-s-1_62
boost_regex -llibboost_regex-clang39-mt-s-1_62 -lboost_regex-mgw62-mt-s-1_62
boost_serialization -llibboost_serialization-clang39-mt-s-1_62 -lboost_serialization-mgw62-mt-s-1_62
boost_signals -llibboost_signals-clang39-mt-s-1_62 -lboost_signals-mgw62-mt-s-1_62
boost_system -llibboost_system-clang39-mt-s-1_62 -lboost_system-mgw62-mt-s-1_62
boost_test_exec_monitor -llibboost_test_exec_monitor-clang39-mt-s-1_62 -lboost_test_exec_monitor-mgw62-mt-s-1_62
boost_thread -llibboost_thread-clang39-mt-s-1_62 -lboost_thread-mgw62-mt-s-1_62
boost_timer -llibboost_timer-clang39-mt-s-1_62 -lboost_timer-mgw62-mt-s-1_62
boost_type_erasure -llibboost_type_erasure-clang39-mt-s-1_62 -lboost_type_erasure-mgw62-mt-s-1_62
boost_unit_test_framework -llibboost_unit_test_framework-clang39-mt-s-1_62 -lboost_unit_test_framework-mgw62-mt-s-1_62
boost_wave -llibboost_wave-clang39-mt-s-1_62 -lboost_wave-mgw62-mt-s-1_62
boost_wserialization -llibboost_wserialization-clang39-mt-s-1_62 -lboost_wserialization-mgw62-mt-s-1_62

To avoid having to manually add these while compiling, we can write all these linking parameters into ST’s build system. Note that the positions of -I and -L should be changed to your own Boost paths. For how to modify the SublimeText build system, you can check my previous article—Configuring SublimeText as a Lightweight IDE for C/C++.

1
2
3
4
{
"name": "Clang++ & Boost",
"cmd": ["cmd", "/c","clang++","-o","${file_base_name}_gxx.exe", "${file}","-std=c++11","-IC:\\Program Files\\BuildPath\\LLVM\\include","-LC:\\Program Files\\BuildPath\\LLVM\\lib","-llibboost_atomic-clang39-mt-s-1_62","-llibboost_chrono-clang39-mt-s-1_62"]
}

Place all the static library linking parameters inside:

Mind the linking order, as the linker will first find the libraries at the front; if the preceding library depends on something from later libraries, it will cause compilation errors. For example, the boost_filename module in Boost depends on boost_system, so the linking for boost_system must come before that for boost_filename.

1
$ clang++ -o test test.cc -std=c++11 -IC:\\Program Files\\BuildPath\\LLVM\\include -LC:\\Program Files\\BuildPath\\LLVM\\lib -llibboost_system-clang39-mt-s-1_62 -llibboost_filesystem-clang39-mt-s-1_62

For more discussion on linking order, you can see here, and discussions on stackoverflow, as well as GCC LD’s sensitivity to input order of dependent libraries.

Additionally, if necessary, you can use -Wl,-Bstatic to specify that the following is statically linked, while -Wl,-Bdynamic indicates that the following is dynamically linked.

Clang version:

1
2
3
4
{
"name": "Clang++",
"cmd": ["cmd", "/c","clang++","-o","${file_path}/${file_base_name}_clangxx.exe", "${file}","-std=c++11","-pthread","-IC:\\Program Files\\CompileBuild\\Boost\\include","-LC:\\Program Files\\CompileBuild\\Boost\\lib\\clang39\\lib","-Wl,-Bstatic","-llibboost_atomic-clang39-mt-s-1_62","-llibboost_container-clang39-mt-s-1_62","-llibboost_date_time-clang39-mt-s-1_62","-llibboost_filesystem-clang39-mt-s-1_62","-llibboost_graph-clang39-mt-s-1_62","-llibboost_iostreams-clang39-mt-s-1_62","-llibboost_log_setup-clang39-mt-s-1_62","-llibboost_log-clang39-mt-s-1_62","-llibboost_math_c99f-clang39-mt-s-1_62","-llibboost_math_c99l-clang39-mt-s-1_62","-llibboost_math_c99-clang39-mt-s-1_62","-llibboost_math_tr1f-clang39-mt-s-1_62","-llibboost_math_tr1l-clang39-mt-s-1_62","-llibboost_math_tr1-clang39-mt-s-1_62","-llibboost_prg_exec_monitor-clang39-mt-s-1_62","-llibboost_program_options-clang39-mt-s-1_62","-llibboost_python-clang39-mt-s-1_62","-llibboost_random-clang39-mt-s-1_62","-llibboost_regex-clang39-mt-s-1_62","-llibboost_serialization-clang39-mt-s-1_62","-llibboost_signals-clang39-mt-s-1_62","-llibboost_type_erasure-clang39-mt-s-1_62","-llibboost_wave-clang39-mt-s-1_62","-llibboost_wserialization-clang39-mt-s-1_62","-llibboost_chrono-clang39-mt-s-1_62","-llibboost_exception-clang39-mt-s-1_62","-llibboost_system-clang39-mt-s-1_62","-llibboost_test_exec_monitor-clang39-mt-s-1_62","-llibboost_thread-clang39-mt-s-1_62","-llibboost_timer-clang39-mt-s-1_62","-llibboost_unit_test_framework-clang39-mt-s-1_62","&&", "start", "console_runner", "${file_path}/${file_base_name}_clangxx.exe"]
}

GCC version (the only difference being using g++ for compilation and not writing the library filenames prefixed with lib (-lboost...)):

1
2
3
4
{
"name": "G++",
"cmd": ["cmd", "/c","g++","-o","${file_path}/${file_base_name}_gxx.exe", "${file}","-std=c++11","-pthread","-IC:\\Program Files\\BuildPath\\Boost\\include","-LC:\\Program Files\\BuildPath\\Boost\\lib\\mingw52\\x64","-Wl,-Bstatic","-lboost_atomic-mgw62-mt-s-1_62","-lboost_container-mgw62-mt-s-1_62","-lboost_date_time-mgw62-mt-s-1_62","-lboost_filesystem-mgw62-mt-s-1_62","-lboost_graph-mgw62-mt-s-1_62","-lboost_iostreams-mgw62-mt-s-1_62","-lboost_log_setup-mgw62-mt-s-1_62","-lboost_log-mgw62-mt-s-1_62","-lboost_math_c99f-mgw62-mt-s-1_62","-lboost_math_c99l-mgw62-mt-s-1_62","-lboost_math_c99-mgw62-mt-s-1_62","-lboost_math_tr1f-mgw62-mt-s-1_62","-lboost_math_tr1l-mgw62-mt-s-1_62","-lboost_math_tr1-mgw62-mt-s-1_62","-lboost_prg_exec_monitor-mgw62-mt-s-1_62","-lboost_program_options-mgw62-mt-s-1_62","-lboost_python-mgw62-mt-s-1_62","-lboost_random-mgw62-mt-s-1_62","-lboost_regex-mgw62-mt-s-1_62","-lboost_serialization-mgw62-mt-s-1_62","-lboost_signals-mgw62-mt-s-1_62","-lboost_type_erasure-mgw62-mt-s-1_62","-lboost_wave-mgw62-mt-s-1_62","-lboost_wserialization-mgw62-mt-s-1_62","-lboost_chrono-mgw62-mt-s-1_62","-lboost_exception-mgw62-mt-s-1_62","-lboost_system-mgw62-mt-s-1_62","-lboost_test_exec_monitor-mgw62-mt-s-1_62","-lboost_thread-mgw62-mt-s-1_62","-lboost_timer-mgw62-mt-s-1_62","-lboost_unit_test_framework-mgw62-mt-s-1_62","&&", "start", "console_runner", "${file_path}/${file_base_name}_gxx.exe"]
}

Note: If the compilation is successful but it prompts that console_runner cannot be found when running, you can download it here and place it in a directory in your PATH (e.g., MinGW/bin).

If you need to set up Boost in VS, you need to configure both win32 and x64 versions based on the x86/x64 versions compiled above in the View -> Property Manager section, so using x86/x64 in VS won’t cause errors.

You can use the following code to test the versions of the compiler and linked libraries:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <boost/version.hpp>
#include <boost/config.hpp>

using namespace std;

int main(int argc,char* argv[])
{
cout << BOOST_VERSION << endl;
cout << BOOST_LIB_VERSION << endl;
cout << BOOST_PLATFORM << endl;
cout << BOOST_COMPILER << endl;
cout << BOOST_STDLIB << endl;
return 0;
}

The compilation results when using G++ and Clang are as follows:

The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:配置SublimeText为Boost开发环境
Author:LIPENGZHA
Publish Date:2016/10/13 09:24
World Count:10k Words
Link:https://en.imzlp.com/posts/49268/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!