使用Amalgamate將C/C++項目合併成一個.h/.c[pp]文件

簡述

C/C++開源庫通常是一堆的頭文件和源文件,作到聲明和實現分離,減少單個模塊大小,這在設計上是很好的,可是用起來稍顯麻煩。在網上看到有好心人推薦了一個開源工具Amalgamate,專門用來對C/C++的頭文件和源文件進行合併用的,因而嘗試了一下。 編譯過sqlite源碼的應該知道,sqlite3源碼包有一個是指包含sqlite3.hsqlite3_ext.hsqlite.c等爲數很少幾個代碼文件的(也有分開的),嵌入到項目中很是方便。這就是用Amalgamate進行合併的。html

下載並編譯Amalgamate

下載很簡單,這裏就不細述了android

git clone https://github.com/vinniefalco/Amalgamate.git

編譯也很簡單,直接使用VS打開Amalgamate\Builds\VisualStudio2010\Amalgamate.vcxproj,而後編譯生成便可。 最後的示例下載中有我編譯的程序。git

# gcc 編譯
g++ Amalgamate.cpp juce_core_amalgam.cpp -o Amalgamate -lpthread -ldl
# clang編譯
clang++ Amalgamate.cpp juce_core_amalgam.cpp -o Amalgamate -lpthread -ldl

具體的使用能夠參考程序的幫助信息。github

將libuv合併爲單一頭文件和源文件版本(Windows下)

用於合併的模板文件編寫能夠參考https://github.com/vinniefalco/Amalgams.git中的幾個。web

libuv爲例進行簡單的說明。 先下載libuv的源碼,目錄結構以下: sql

首先先合併頭文件

先編寫一個頭文件uv_all.h,裏面把libuv-v1.9.1\include下的文件都include進來。 源碼以下:windows

#include "android-ifaddrs.h"
#include "pthread-barrier.h"
#include "stdint-msvc2008.h"
#include "tree.h"
#include "uv.h"
#include "uv_all.h"
#include "uv-errno.h"
#include "uv-threadpool.h"
#include "uv-version.h"
#include "uv-win.h"

一個簡單的作法就是cygwin或msys下使用命令ls *.h |xargs -I{} echo '#include "{}"'直接輸出。 由於我這裏只作windows平臺的,因此把多餘的都給刪除了。 實際上由於uv.h已經把須要的都包含上了,因此這裏直接使用uv.h也就夠了。 運行下面命令生成合並後的頭文件api

Amalgamate.exe -i C:\Users\o\Documents\code\libuv-v1.9.1\include  -w "*.h;*.c"  C:\Users\o\Documents\code\libuv-v1.9.1\include\uv.h  uv.h

執行完上面命令後會在當前目錄生成一個新的uv.h文件,也就是合併後的文件。上面參數中-i後面的是附加包含目錄,也就是和gcc中使用的-I是同樣的。最後的uv.h是輸出文件名,前面的是輸入的配置模板文件。bash

合併源碼文件

合併源碼文件的作法和合並頭文件的作法是一致的,先寫一個配置文件uv_win_all.h(把src和src/win目錄下全部文件都包含進來),內容以下:async

#include "win/atomicops-inl.h"
#include "win/handle-inl.h"
#include "win/internal.h"
#include "win/req-inl.h"
#include "win/stream-inl.h"
#include "win/winapi.h"
#include "win/winsock.h"

#include "heap-inl.h"
#include "queue.h"
#include "uv-common.h"

#include "win/async.c"
#include "win/core.c"
#include "win/dl.c"
#include "win/error.c"
#include "win/fs.c"
#include "win/fs-event.c"
#include "win/getaddrinfo.c"
#include "win/getnameinfo.c"
#include "win/handle.c"
#include "win/loop-watcher.c"
#include "win/pipe.c"
#include "win/poll.c"
#include "win/process.c"
#include "win/process-stdio.c"
#include "win/req.c"
#include "win/signal.c"
#include "win/snprintf.c"
#include "win/stream.c"
#include "win/tcp.c"
#include "win/thread.c"
#include "win/timer.c"
#include "win/tty.c"
#include "win/udp.c"
#include "win/util.c"
#include "win/winapi.c"
#include "win/winsock.c"

#include "fs-poll.c"
#include "inet.c"
#include "threadpool.c"
#include "uv-common.c"
#include "version.c"

而後執行下面命令進行合併

Amalgamate.exe -i C:\Users\o\Documents\code\libuv-v1.9.1\include -i C:\Users\o\Documents\code\libuv-v1.9.1\src  -w "*.h;*.c"   C:\Users\o\Documents\code\libuv-v1.9.1\src\uv_win_all.c uv_win.c

合併後的文件中會遇到一些問題,須要手動修改一下。好比多出遇到uv_zero_重定義的問題,這個須要把第一次定義以後出現的都所有註釋掉。 還有會遇到error LNK2019: 沒法解析的外部符號 _InterlockedOr,該符號在函數 _uv_tty_line_read_thread@4 中被引用的問題,這個只須要使用VS2012以後的版本編譯就沒問題了。

合併後的源碼及項目文件

這裏很少說,直接放出下載連接 https://files.cnblogs.com/files/oloroso/libuv_webtest.7z

測試的代碼部分來自於https://github.com/liigo/tinyweb.git

Amalgamate參數簡單說明

參數 解釋
-s 處理#include <xxx>的行,即處理包含在系統目錄中的頭文件(一般咱們只須要處理雙引號括起來的)
-w{wildcards} 指定要處理的文件類型(後綴名),若是不是列表中指定的,那麼即使使用#include包含也不會處理,默認設置是".cpp;.c;.h;.mm;*.m"
-f `{file macro}`
-p `{file macro}`
-d {name}={file} 若是宏{name}出如今include包含行中,使用{file}替代
-i {dir} 在處理include包含時,能夠在指定的{dir}目錄中搜索文件
-v 輸出詳細信息
相關文章
相關標籤/搜索