我想将Boost Preprocessor库(以及最终其他的)捆绑到一个合并的标题中,所以我将一个小的实用程序组合在一起以实现这个目标......只是它没有工作!我无法确定我的程序中的错误或实施问题(或两者)是否导致其无法正常工作。
程序应该打开boost\preprocessor\library.hpp
标题(包括整个库)并递归输出到stdout
库所需的所有标题。 Windows资源管理器报告目录树中有(自Boost预处理器v1.59.0起)270个头文件,但我的程序只解析了204个。
我在另一个使用Boost预处理器的项目中使用它来测试合并的头。当使用boost\preprocessor\library.hpp
标题时,项目编译并正常工作,但是当使用我的合并版本时,由于没有找到所需的所有Boost预处理器宏,编译失败。
完整的,可编译的代码:(仅使用MSVC v19进行测试)
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <unordered_map>
// Remember what header files have already been parsed.
std::unordered_map<std::string, bool> have_parsed;
char include_dir[FILENAME_MAX]; // Passed in from the command line.
// Advance given pointer to next non-whitespace character and return it.
char* find_next_nonwhitespace_char(char* start) {
while(isspace((int)(*start)) != 0) start++;
return start;
}
#define DIE(condition, str) if(condition) {perror(str); exit(EXIT_FAILURE);}
int headers_parsed = 0;
void parse_header(const char* filename) {
headers_parsed++;
char path[FILENAME_MAX];
strcpy(path, include_dir);
strcat(path, filename);
// Open file, get size and slurp it up.
FILE* file = fopen(path, "rb");
DIE(file == NULL, "fopen()");
fseek(file, 0L, SEEK_END);
long int file_size = ftell(file);
rewind(file);
char* file_buffer = (char*)malloc(file_size+1); // +1 for extra '\0'
DIE(file_buffer == NULL, "malloc()");
size_t got = fread(file_buffer, 1, file_size, file);
DIE(got != file_size, "fread()");
fclose(file);
char* read_index = file_buffer;
char* end_of_file = file_buffer + file_size;
*end_of_file = '\0';
// File is now in memory, parse each line.
while(read_index < end_of_file) {
char* start_of_line = read_index;
// Scan forward looking for newline or 'EOF'
char* end_of_line = strchr(start_of_line, '\n');
if(end_of_line == NULL) end_of_line = end_of_file;
*end_of_line = '\0';
// Advance to the start of the next line for the next read.
read_index += (end_of_line - start_of_line) + 1;
// Look for #include directive at the start of the line.
char* first_char = find_next_nonwhitespace_char(start_of_line);
if(*first_char == '#') {
// This could be an include line...
char* next_char = find_next_nonwhitespace_char(first_char + 1);
const char include[] = "include ";
if(strncmp(next_char, include, strlen(include)) == 0) {
char* open_brace = find_next_nonwhitespace_char(next_char + strlen(include));
if(*open_brace++ == '<') {
char* close_brace = strchr(open_brace, '>');
assert(close_brace != NULL);
*close_brace = '\0';
if(have_parsed[open_brace] == false) {
have_parsed[open_brace] = true;
parse_header(open_brace); // Recurse
}
continue;
}
}
}
fprintf(stdout, "%s\n", start_of_line);
}
free(file_buffer);
}
int main(int argc, char* argv[]) {
if(argc < 3) {
fprintf(stderr, "%s {include directory} {first header}\n", argv[0]);
return EXIT_FAILURE;
}
// Ensure the include directory has trailing slash
strcpy(include_dir, argv[1]);
size_t len = strlen(argv[1]);
if(include_dir[len-1] != '\\') {
include_dir[len] = '\\';
include_dir[len+1] = '\0';
}
parse_header(argv[2]);
fprintf(stderr, "headers parsed: %d\n", headers_parsed);
return EXIT_SUCCESS;
}
运行已编译的程序:( Boost安装在g:\ dev中)
g:\dev\amalgamate\amalgamate.exe g:\dev\ boost\preprocessor\library.hpp > boost_pp.h
headers parsed: 204
生成的boost_pp.h
标题:https://copy.com/vL6xdtScLogqnv9z
出了什么问题? 为什么我的程序没有创建一个有效的合并标题?
答案 0 :(得分:5)
library.hpp
实际上不包括树中的某些标题,原因是:
他们将其他标头包装为外部接口(或因为它们已被弃用),例如preprocessor/comma.hpp
只包含preprocessor/punctuation/comma.hpp
,
将通过宏包含,例如:
# define BOOST_PP_ITERATE() BOOST_PP_CAT(BOOST_PP_ITERATE_, BOOST_PP_INC(BOOST_PP_ITERATION_DEPTH()))
#
# define BOOST_PP_ITERATE_1 <boost/preprocessor/iteration/detail/iter/forward1.hpp>
# define BOOST_PP_ITERATE_2 <boost/preprocessor/iteration/detail/iter/forward2.hpp>
# define BOOST_PP_ITERATE_3 <boost/preprocessor/iteration/detail/iter/forward3.hpp>
# define BOOST_PP_ITERATE_4 <boost/preprocessor/iteration/detail/iter/forward4.hpp>
# define BOOST_PP_ITERATE_5 <boost/preprocessor/iteration/detail/iter/forward5.hpp>
可用于:
#define BOOST_PP_ITERATION_PARAMS_1 (...)
#include BOOST_PP_ITERATE()