簡體   English   中英

使用 make 構建 C++ 模板庫

[英]Building a C++ template library with make

我在將我的 C++ 庫重寫為模板形式時遇到了困難; 主要問題涉及重新設計Makefile

在之前的 state 中,當它是非模板時,我有:

  • 一個 header 文件lib.h ,其中(受包含保護)我們有類和重載運算符的聲明。 該文件根本不包含任何其他庫。
  • 一個實現文件lib.cpp ,在該文件的頂部,我包含了來自標准庫(cmath、iostream 等)的許多頭文件,並包含了此自定義庫的 header 文件: #include "lib.h"
  • 帶有用於構建/安裝庫的命令的Makefile
CC = g++
CFLAGS = -O2
SRC = lib.cpp
HDR = $(SRC:.cpp=.h)
OBJ = $(SRC:.cpp=.o)
LIB = $(OBJ:.o=.a)

.PHONY: all install clean uninstall

# =========================================================
# Build
# =========================================================

all: $(LIB)

# Create an object file
$(OBJ):
    $(CC) $(CFLAGS) -c -o $@ $(SRC)

# Create a static library file
$(LIB): $(OBJ)
    ar rcs $@ $<

# =========================================================
# Install
# =========================================================

install: ~/lib/lib/$(LIB) ~/lib/include/$(HDR)

# Create top-level directory for the libraries
~/lib:
    mkdir -p $@;

# Create top-level directory for the static library files
~/lib/lib:
    mkdir -p $@;

# Create top-level directory for the headers
~/lib/include:
    mkdir -p $@;

# Copy the library file into the right directory
~/lib/lib/$(LIB): $(LIB) ~/lib/lib
    cp $< $@

# Copy the header file into the right directory
~/lib/include/$(HDR): $(HDR) ~/lib/include
    cp $< $@
  • 安裝后,我的 CI (GH Actions) 將編譯一個小型測試程序,其中包括我的庫 header ( #include <lib.h> ),使用以下命令:
g++ -O0 -Wall --std=c++14 test.cpp -I ~/lib/include/ ~/lib/lib/lib.a -o test

此設置運行良好。


現在問題出現了,當我想將我的 class 重新編寫為模板時。

根據這篇文章中的信息,我在我的庫的 header 文件的末尾添加了一個#include "lib.cpp" (在包含保護中,ofc)。 通過該更改,我需要調整編譯過程並且不在命令行中提供我的實現文件(因為它已經包含在 header 中,我必須避免重新定義錯誤)。 這很好用。 問題的核心現在在Makefile中,在命令中構建一個 object 文件。 當我嘗試編譯我的庫的實現文件時,它包含 header 和 header 再次包含實現......我對此端口中的問題表示懷疑,他們建議從實現文件中刪除 Z099FB995346F31C735E40E3ZF 包含。 所以我這樣做了,我評論了#include "lib.h"並嘗試運行:

g++ -O2 -c -o lib.o lib.cpp

最后我遇到了很多error: use of undeclared identifier錯誤......

如何使用make正確構建庫? 我的限制是該庫位於兩個單獨的文件中: header 和 implementation 我最終想要的是能夠在我的進一步程序中#include <lib.h>

甚至可以創建存檔的 object 文件嗎? 共享 object 庫( .so )怎么樣?

我在我的庫的 header 文件的末尾添加了一個#include "lib.cpp" (在包含保護中,ofc)。

我不能說我認為你在那里遵循的建議很多。 旨在用作 header 或用於 header 的代碼應適當命名( .h.hpp或您的項目遵循的任何約定),適合直接編譯的代碼幾乎不屬於 header。 也許您的轉換涉及將后一種類型的所有內容更改為前一種類型,因此您可能想將lib.cpp重命名為lib_impl.h或類似名稱,並完全跳過編譯它的嘗試。 也許。

但是請注意,如果您將實現代碼命名和構建為 header,那么它需要自己的包含防護。 還要注意,它不能包含任何外部的非模板函數。 如果是這樣,那么沒有兩個獨立的翻譯單元可以同時包含 header,因為這將導致重復的 function 定義,盡管包括警衛。 如果沒有外部的非模板函數(也沒有外部的 object 定義),那么嘗試編譯為 object 文件是沒有意義的,因為在其中沒有任何 ZC1C425268E68385D14AB5074C17A 的可訪問入口點。

如何使用make正確構建庫?

這實際上與make無關。 這只是提供自動化。 問題在於圖書館本身的結構和您的期望。

我的限制是該庫位於兩個單獨的文件中: header 和 implementation

僅當實現包含外部對象或函數的任何實例化模板或任何外部非模板函數或對象時,此約束才有意義。 這些將有助於構建可構建的 object 文件,您可以直接或間接鏈接到應用程序。 如果轉換為模板庫意味着您的庫中不再有任何此類實體,則約束是任意的,因為轉換后的結果是僅包含標頭的庫。 不過,您可以按照自己喜歡的方式拆分標題,只要每個生成的標題結構header,僅包含適合 header 的內容,並具有自己的包含保護。

另一方面,如果您轉換后的實現代碼確實包含任何這些內容,那么它們不得將#include d 放入任何 header 中,如上所述。

我最終想要的是能夠在我的進一步程序中#include <lib.h>

如果轉換后的實現代碼適合用作 header 或在 header 中使用,那么您已經在那里,但是將您的lib.cpp重命名為 header 會更好。 如果您希望能夠將 header 直接包含到主庫 header 以外的代碼中,那么它需要自己的包含保護——這將處理重復的聲明。 但是請注意,這些錯誤源於您具有循環依賴這一事實,這是您應該重構的強烈跡象。 這樣的重構將涉及將足夠的代碼從lib.cpp移動到lib.h ,以便可以刪除循環依賴項(其中一個文件將不再#include另一個)。

任何不適合在 header 中使用的實現代碼顯然都不能包含在 header 中。 如果任何此類代碼保留在轉換后的庫中,那么也許您將其保留在lib.cpp中,並將 rest 移動到lib.h

甚至可以創建存檔的 object 文件嗎? 共享 object 庫(.so)怎么樣

無法編譯模板。 它們是可以編譯的代碼模板:它們的實例化。 如果您的轉換沒有留下任何其他內容,那么您將無法有效地創建 object 文件或共享庫。 而且您不需要這樣做,因為這是一個僅標頭庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM