简体   繁体   English

部分编译并在makefile中包含boost(C ++)

[英]Partially compile and include boost with makefile (c++)

I have a project in c++ that I want to be reasonably portable, and can be compiled by issuing a single "make" command. 我有一个c ++项目,我希望它具有一定的可移植性,并且可以通过发出单个“ make”命令进行编译。 I currently use boost headers for certain operations, but now need "filesystem" from boost, which requires compilation. 我目前对某些操作使用boost标头,但现在需要boost的“文件系统”,需要编译。

I know there is a way to compile boost using the included shell script, but that takes FOREVER. 我知道有一种方法可以使用包含的shell脚本来编译boost,但这需要永远。 I am curious of a way to selectively compile boost libraries, as specified from a makefile and include them in the linking process. 我很好奇一种方法,可以有选择地编译一个makefile中指定的boost库,并将它们包含在链接过程中。

My current general idea is: 我目前的总体思路是:

  1. Have a makefile variable of the boost libraries wanted to be compiled and included. 有想要编译和包含的boost库的makefile变量。

  2. Compile those libraries (before any dependent projects) from a boost distribution folder, AND output compiled binaries to a specific folder in the makefile project (eg: a "lib" folder) 从boost分发文件夹中编译这些库(在任何依赖项目之前),并将已编译的二进制文件输出到makefile项目中的特定文件夹(例如:“ lib”文件夹)

  3. I understand how to have these files included in the project by using: 我了解如何使用以下方法将这些文件包含在项目中:

    -Llib -Llib

What is the best way to do this, as well as choose where the boost output from compilation is? 做到这一点的最佳方法是什么,以及选择编译的增强输出在哪里? Should the files be .a or .o files? 文件应该是.a还是.o文件? (or no extension?) (或没有扩展名?)

This is the wilder older brother of the prior answer's manual makefile. 这是先前答案的手动makefile的更老的兄弟。 Given a path to the BOOST distro, BOOST_DISTRO , it finds the relevant source files for the target libs specified in TARGET_BOOST_LIBS , compiles them into $(WORK_FOLDER)/<lib>/ , and archives the resulting objects into $(DEST_FOLDER)/libboost_<lib>.a . 给定BOOST发行版的路径BOOST_DISTRO ,它找到TARGET_BOOST_LIBS指定的目标库的相关源文件,将它们编译为$(WORK_FOLDER)/<lib>/ ,并将生成的对象归档到$(DEST_FOLDER)/libboost_<lib>.a

BOOST_DISTRO=.
DEST_FOLDER=libs
WORK_FOLDER=build

TARGET_BOOST_LIBS=\
  system \
  filesystem \
  serialization

.PHONY: all
all: $(foreach lib,$(TARGET_BOOST_LIBS),$(DEST_FOLDER)/libboost_$(lib).a )

$(DEST_FOLDER):
    mkdir -p $(DEST_FOLDER)

$(WORK_FOLDER):
    mkdir -p $(WORK_FOLDER)

#####
# helper for building the .o files in WORK_FOLDER
#####
define MAKE_BOOST_LIB_COMPILE_RULES
$(foreach cppfile,$(shell ls $(BOOST_DISTRO)/boost/libs/$(1)/src/*.cpp),$(WORK_FOLDER)/$(1)/$(notdir $(cppfile:.cpp=.o)): $(cppfile) | $(WORK_FOLDER)/$(1)
    $(CXX) $(CXXFLAGS) -D BOOST_ALL_NO_LIB \
          -I$(BOOST_DISTRO)/boost \
          -c $$^ \
          -o $$@
)
endef


#####
# define the build rules based on the files we find in the subfolders of
# the boost distro that correspond to our library names
#####
define BUILD_BOOST_LIB
$(WORK_FOLDER)/$(1): | $(WORK_FOLDER)
    mkdir -p $$@
$(call MAKE_BOOST_LIB_COMPILE_RULES,$(1))
$(DEST_FOLDER)/libboost_$(1).a: $(foreach cppfile,$(notdir $(shell ls $(BOOST_DISTRO)/boost/libs/$(1)/src/*.cpp)),$(WORK_FOLDER)/$(1)/$(cppfile:.cpp=.o)) | $(DEST_FOLDER)
    ar r $$@ $$^
    ranlib $$@
endef


#####
# dynamically generate the build rules from the list of libs
#####
$(foreach lib,$(TARGET_BOOST_LIBS),$(eval $(call BUILD_BOOST_LIB,$(lib))))

.PHONY: clean
clean:
    -rm -rf $(WORK_FOLDER)
    -rm -rf $(DEST_FOLDER)

Testing with my ancient BOOST ( #define BOOST_VERSION 105500 ), this builds the listed libs, and a dummy test program successfully compiles and calls boost::filesystem::absolute() . 使用我古老的BOOST( #define BOOST_VERSION 105500 )进行测试,这将构建列出的库,并且一个虚拟测试程序会成功编译并调用boost::filesystem::absolute()

Using lockcmpxchg8b's answer, I was able to adapt it to my needs. 使用lockcmpxchg8b的答案,我可以使其适应我的需求。

It was a little tricky to get makefiles to work right when recursively called, but I was able to get it to work. 在递归调用时使makefile正常工作有点棘手,但我能够使其正常工作。

SHELL = /bin/sh

# This makefile expects multiple arguments to be passed:
#
# Use the pattern: make var_name="var_value" when invoking this makefile
#
# BOOST_VER (the version suffix )
# BOOST_LIBS_TO_BUILD (space delimited list of boost libraries to build)
# BOOST_LIB_DIR (the output lib dir for the boost libraries)
# BOOSTDIR (the base directory to build from)
#

# Compile Info
CXX = g++
CXXFLAGS = -Wall -std=c++11

WORK_FOLDER = obj_boost$(BOOST_VER)

.PHONY: all
all: $(foreach lib,$(BOOST_LIBS_TO_BUILD),$(BOOST_LIB_DIR)/libboost_$(lib).a )

$(BOOST_LIB_DIR):
    @mkdir -p $(BOOST_LIB_DIR)

$(WORK_FOLDER):
    @mkdir -p $(WORK_FOLDER)

#####
# helper for building the .o files in WORK_FOLDER
#####
define MAKE_BOOST_LIB_COMPILE_RULES
$(foreach cppfile,$(shell ls $(BOOSTDIR)/libs/$(1)/src/*.cpp),$(WORK_FOLDER)/$(1)/$(notdir $(cppfile:.cpp=.o)): $(cppfile) | $(WORK_FOLDER)/$(1)
        $(CXX) $(CXXFLAGS) -D BOOST_ALL_NO_LIB \
                    -I$(BOOSTDIR) \
                    -c $$^ \
                    -o $$@
)
endef

#####
# define the build rules based on the files we find in the subfolders of
# the boost distro that correspond to our library names
#####
define BUILD_BOOST_LIB
$(WORK_FOLDER)/$(1): | $(WORK_FOLDER)
        @mkdir -p $$@
$(call MAKE_BOOST_LIB_COMPILE_RULES,$(1))
$(BOOST_LIB_DIR)/libboost_$(1).a: $(foreach cppfile,$(notdir $(shell ls $(BOOSTDIR)/libs/$(1)/src/*.cpp)),$(WORK_FOLDER)/$(1)/$(cppfile:.cpp=.o)) | $(BOOST_LIB_DIR)
        @ar r $$@ $$^
        @ranlib $$@
endef

#####
# dynamically generate the build rules from the list of libs
#####
$(foreach lib,$(BOOST_LIBS_TO_BUILD),$(eval $(call BUILD_BOOST_LIB,$(lib))))

.PHONY: clean
clean:
        @rm -rf $(WORK_FOLDER)
        @rm -rf $(BOOST_LIB_DIR)/*
        @echo "---- Done Cleaning Boost Libs ----"

To call this makefile, I call it from another makefile using the following: 要调用此makefile,我使用以下命令从另一个makefile调用它:

# Boost
BOOST_VER= _1_65_1

BOOST_LIBS_TO_BUILD = filesystem timer chrono
#relative to this file
BOOST_LIB_DIR = shared/lib_boost$(BOOST_VER)
#relative to this file
BOOSTDIR = shared/boost$(BOOST_VER)

#Subdirectories
DIRECTORIES = $(sort $(dir $(wildcard */makefile)))

.PHONY: build
build: dependencies
        @$(foreach dir,$(DIRECTORIES),$(MAKE) -C $(dir);)

dependencies:
        @echo "---- Build Dependencies ----"
        @$(MAKE) -C shared -f build_boost_libs.mk BOOST_LIBS_TO_BUILD="$(BOOST_LIBS_TO_BUILD)" BOOST_LIB_DIR="../$(BOOST_LIB_DIR)" BOOSTDIR="../$(BOOSTDIR)" BOOST_VER="$(BOOST_VER)"

The pattern to CORRECTLY invoke a recursive make is: 正确调用递归生成的模式是:

$(MAKE) -C subdir_of_makefile -f makefile_name.mk

The use of $(MAKE) is the proper way to invoke make (as per documentation -- it ensures the same make command is used as the top-most make) and to correctly change the running directory, you need to use the -C argument (otherwise the directory context of any sub-make is the top-most parent makefile in the call stack). 使用$(MAKE)是调用make的正确方法(根据文档 -确保使用相同的make命令作为最顶层的make)并正确更改运行目录,您需要使用-C参数(否则,任何子make的目录上下文都是调用堆栈中最顶层的父makefile)。 The -f option specifies a makefile that is anything but a default name for a makefile. -f选项指定一个makefile,除了makefile的默认名称以外,它什么都没有。 This takes into account the -C option when looking for the named makefile. 查找命名的makefile时,这考​​虑了-C选项。

I also found out that passing "arguments" to a makefile is a bit tricky, and is usually done with export and unexport, but the problem with those is due to ONLY the LAST "status" of a variable to be exported is used for the ENTIRE makefile. 我还发现,将“参数”传递给makefile有点棘手,通常是通过export和unexport完成的,但是这些问题是由于仅将要导出的变量的LAST“ status”用于整个makefile。 You can't export a variable, call a sub-make, then unexport. 您无法导出变量,无法调用子make,然后取消导出。 It would be unexported for the entire makefile run (as the last "status" of the variable was to be unexported despite it being called after the sub-make). 在整个makefile运行中,它将不导出(因为变量的最后一个“状态”将在子make之后被调用,但仍要导出)。 Variable "status" is computed/parsed before the makefile executes. 在生成文件执行之前,将计算/解析变量“状态”。

Thanks for the help! 谢谢您的帮助! I appreciate it. 我很感激。 I'll also be releasing this makefile in an open-source project in the future (I'll credit your username as helping with that) 将来,我还将在一个开源项目中发布此Makefile(我相信您的用户名会对此有所帮助)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM