2010-09-02 65 views
63

Tôi muốn chương trình sử dụng Qt, nhưng tôi không muốn sử dụng các trình biên dịch đặc biệt hoặc IDE như Qt Creator và qmake. Tôi muốn viết với Kate và biên dịch với g ++.Tôi có thể sử dụng Qt mà không cần qmake hoặc Qt Creator không?

Tôi có thể biên dịch chương trình sử dụng Qt với g ++ không? Làm thế nào để biên dịch nó với g + +?

+12

Tôi có thể hiểu không muốn sử dụng Trình tạo Qt, nhưng tại sao không sử dụng qmake? Tất cả qmake làm là tạo ra một Makefile cho bạn; nếu bạn không sử dụng qmake, bạn sẽ phải tự viết cùng một Makefile, và tệ hơn là bạn sẽ phải duy trì một Makefile khác nhau cho mỗi nền tảng mà bạn muốn biên dịch theo. Với qmake bạn chỉ phải tạo một file .pro, thay vì phải nhớ cách một MakeVile của MSVC khác với Makefile gnu, v.v. –

+6

Vì tôi muốn biết điều gì xảy ra trong quá trình biên dịch thay vì sử dụng một công cụ tự động. Nó dễ dàng hơn với qmake hoặc Qt Creator, nhưng tôi thích thực hiện tác vụ này một cách thủ công. – Squall

+2

Vì vậy, bạn muốn viết makefiles của bạn bằng tay, thay vì sử dụng một máy phát điện như qmake, cmake hoặc autotools? Lý do duy nhất cho điều đó là nếu bạn muốn tìm hiểu cú pháp Makefile. Kết quả sẽ là một gánh nặng bảo trì, không phải di động, vv –

Trả lời

34

Chắc chắn bạn có thể. Mặc dù nó là thuận tiện hơn với qmake hoặc CMake, bạn có thể làm:

CXXFLAGS += -Ipath_to_your_qt_includes 
LDFLAGS += -Lpath_to_your_qt_libs 

LDLIBS += -lqt-mt (for Qt3) 

hoặc

LDLIBS += -lQtCore -lQtGui (for Qt4, add what you need) 

my_prog: my_prog.cpp 

(trong một makefile)

Update - cách gọi moc:

Trích từ moc manpage :

Đây là một quy tắc makefile hữu ích nếu bạn chỉ sử dụng GNU thực hiện:

m%.cpp: %.h 
     moc $< -o [email protected] 

Cá nhân tôi muốn đặt tên cho sản lượng khá %.moc.cpp (hơn m%.cpp). Sau đó bạn có thêm sự phụ thuộc của my_prog trên my_prog.moc.cpp

my_prog: my_prog.cpp my_prog.moc.cpp 

Tương tự như vậy cho uic. Tình huống ở đây phức tạp hơn, vì bạn phải tạo quy tắc cho các tiêu đề tệp nguồn và bạn phải thêm phụ thuộc vào tệp tiêu đề để đảm bảo nó được tạo trước khi các nguồn được biên dịch. Một cái gì đó như thế này có thể hoạt động:

my_prog: my_prog.o my_prog.moc.o my_prog.ui.o 
     $(CXX) $(LDFLAGS) -o my_prog $^ $(LDLIBS) 

my_prog.o: my_prog.cpp my_prog.ui.h 
+2

Ngoài ra, nếu bạn sử dụng cú pháp mở rộng của Qt như tín hiệu và vị trí, bạn cần phải chạy thủ công theo cách thủ công. Đó là trình biên dịch đặc biệt "bắt buộc" duy nhất. – teukkam

+2

Và câu trả lời này không chỉ cho bạn cách chạy 'moc' (một cái gì đó mà nó ** rất cần ** để chứng minh) –

+1

@teukkam, @Ken Bloom: xem chỉnh sửa – jpalecek

18

Bạn chắc chắn không phải sử dụng QtCreator để viết chương trình Qt.

Bạn cũng không phải sử dụng qmake nhưng bạn đang gặp sự cố khi không sử dụng.

Để làm bất cứ điều gì thậm chí từ xa thú vị trong Qt, bạn chắc chắn sẽ kết thúc phân lớp QObject. Tất cả các lớp con này yêu cầu macro Q_OBJECT trong định nghĩa của chúng cho phép cú pháp tín hiệu/khe. Cú pháp này không phải là C++ thông thường và không thể được biên dịch bằng cách sử dụng g ++. Tệp có chứa định nghĩa lớp học với Q_OBJECT phải được chạy qua số meta-object compiler của Qt được gọi là moc. Điều này có nghĩa là bạn phải tìm ra các tệp cần phải có moc áp dụng cho chúng, sau đó chạy moc trên chúng, rồi biên dịch tệp cpp kết quả bằng g++. Đây là lý do Qt cung cấp qmake. Nó tạo ra các quy tắc chính xác trong Makefile cho bạn.

Tệp dự án Qt .pro thực sự khá đơn giản để làm việc và tôi thực sự khuyên bạn nên sử dụng chúng. Hãy nhớ rằng, qmake là công cụ dòng lệnh giống như g++. Ngoài ra, nó thực sự có thể tạo ra một tập tin dự án khung cho bạn bằng cách cung cấp các tùy chọn để -project để bắt đầu bạn chỉ có thể làm

qmake -project 
qmake 
make 

và bạn đã làm xong.Trên thực tế tôi thấy rằng hồ sơ dự án tạo ra có thể bị thiếu việc kê khai của bất kỳ thư viện Qt thêm tôi có thể sử dụng, do đó bạn có thể phải thêm một dòng như

QT += opengl 

nếu, ví dụ, bạn đã bao gồm cái gì đó như QGLWidget .

+2

cho tất cả các mục đích và mục đích, Qt là khá vô dụng mà không có QMake. Câu trả lời hay. –

+0

Thực ra, bạn có thể quyết định sử dụng phần mở rộng .qpp cho các tệp cần moc'ing. Điều này cho phép bạn tạo quy tắc thực hiện (hoặc quy tắc xây dựng Visual Studio tùy chỉnh). Tệp .cpp được tạo sẽ được biên dịch bình thường. – MSalters

+1

Câu trả lời này gây hiểu nhầm. Qmake là một công cụ xây dựng và độc lập với moc. Bạn có thể gọi moc thành công và dễ dàng từ một công cụ xây dựng khác. Tôi đã làm điều này trong Visual Studio và SCons chẳng hạn. Trong cả hai dễ dàng của nó để có điều này xử lý minh bạch để bạn có thể thực hiện như bình thường, như thể moc không tồn tại. – JBentley

0

Một số trình biên dịch trước là cần thiết cho Qt projcet, như moc, uic, ..., v.v. Qt Creator + qmake rất thuận tiện để thực hiện những việc như vậy và tạo một makefile cho các trình biên dịch g ++ hoặc msvc.

5

Đây là makefile của tôi cho bất kỳ dự án Qt mà không sử dụng qmake:

#--------------------------------------------------------------------------------- 
# Compiler executables 
#--------------------------------------------------------------------------------- 
CC  := gcc 
CXX  := g++ 

#--------------------------------------------------------------------------------- 
# Options for code generation 
#--------------------------------------------------------------------------------- 
DEFINES := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED 
CFLAGS := -g -Wall $(DEFINES) 
CXXFLAGS:= $(CFLAGS) 
LDFLAGS := -g -Wl 

#--------------------------------------------------------------------------------- 
# Any extra libraries you wish to link with your project 
#--------------------------------------------------------------------------------- 
LIBS := -lQtGui -lQtCore -lpthread 

#--------------------------------------------------------------------------------- 
# Some more include paths 
#--------------------------------------------------------------------------------- 
INCPATHS:= -I/usr/share/qt4/mkspecs/default -I/usr/include/QtGui -I/usr/include/QtCore 

#--------------------------------------------------------------------------------- 
# Source folders and executable name 
#--------------------------------------------------------------------------------- 
TARGET := $(shell basename $(CURDIR)) 
BUILD := build 
SOURCES := source 
INCLUDES:= source include 

#--------------------------------------------------------------------------------- 
# Source files 
#--------------------------------------------------------------------------------- 
ifneq ($(BUILD),$(notdir $(CURDIR))) 
#--------------------------------------------------------------------------------- 
export OUTPUT := $(CURDIR)/$(TARGET) 

export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 
        $(foreach dir,$(INCLUDES),$(CURDIR)/$(dir)) 

CFILES  := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 
HFILES  := $(foreach dir,$(INCLUDES),$(notdir $(wildcard $(dir)/*.h))) 

#--------------------------------------------------------------------------------- 
# Use CXX for linking C++ projects, CC for standard C 
#--------------------------------------------------------------------------------- 
ifeq ($(strip $(CPPFILES)),) 
#--------------------------------------------------------------------------------- 
    export LD := $(CC) 
#--------------------------------------------------------------------------------- 
else 
#--------------------------------------------------------------------------------- 
    export LD := $(CXX) 
#--------------------------------------------------------------------------------- 
endif 
#--------------------------------------------------------------------------------- 

export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(HFILES:.h=.moc.o) 

export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) $(INCPATHS) 

#--------------------------------------------------------------------------------- 
.PHONY: $(BUILD) clean install uninstall 
#------------------------------------------------------------------------------ 
$(BUILD): 
    @[ -d [email protected] ] || mkdir -p [email protected] 
    @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 

#--------------------------------------------------------------------------------- 
clean: 
    @echo clean ... 
    @rm -fr $(BUILD) $(TARGET) 

#--------------------------------------------------------------------------------- 
install: 
    @cp -u $(TARGET) /usr/bin/$(TARGET) 
    @echo installed. 

#--------------------------------------------------------------------------------- 
uninstall: 
    @rm -f /usr/bin/$(TARGET) 
    @echo uninstalled. 

#--------------------------------------------------------------------------------- 
else 
#--------------------------------------------------------------------------------- 
# Makefile targets 
#--------------------------------------------------------------------------------- 
all: $(OUTPUT) 

#--------------------------------------------------------------------------------- 
$(OUTPUT): $(OFILES) 
    @echo built ... $(notdir [email protected]) 
    @$(LD) $(LDFLAGS) $(OFILES) -o [email protected] $(LIBS) 

#--------------------------------------------------------------------------------- 
%.o: %.c 
#--------------------------------------------------------------------------------- 
    @echo $(notdir $<) 
    @$(C) $(CFLAGS) $(INCLUDE) -c $< -o [email protected] 

#--------------------------------------------------------------------------------- 
%.o: %.cpp 
#--------------------------------------------------------------------------------- 
    @echo $(notdir $<) 
    @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o [email protected] 

#--------------------------------------------------------------------------------- 
%.moc.cpp: %.h 
#--------------------------------------------------------------------------------- 
    @echo $(notdir $<) 
    @moctool $< $(DEFINES) $(INCLUDE) -o [email protected] 

#--------------------------------------------------------------------------------- 
%.moc.o: %.moc.cpp 
#--------------------------------------------------------------------------------- 
    @echo $(notdir $<) 
    @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o [email protected] 

#--------------------------------------------------------------------------------- 
endif 
#--------------------------------------------------------------------------------- 

Ở đây, moctool là một công cụ đơn giản giúp cho tiêu đề không QObject, đây là mã nguồn của nó:

https://github.com/Quent42340/EasyLib/blob/master/tools/moctool/source/main.cpp

+0

Tôi nhận thấy đây là cũ, nhưng câu trả lời này là _exactly_ những gì tôi đang cố gắng làm trên dự án hiện tại của tôi. Tuy nhiên, tôi đang đấu tranh với sự hiểu biết một vài bit của logic. Đầu tiên, dòng 36: 'ifneq ($ (BUILD), $ (notdir $ (CURDIR)))' dường như kiểm tra xem makefile có được thực hiện từ thư mục build hay không, nếu không nó có vẻ gọi một '@make --no- khác print-directory -C $ (BUILD) -f $ (CURDIR)/Makefile' trên dòng 71. Tại sao? Tất cả mọi thứ xảy ra sau khi 'else' trên dòng 93 bắt đầu với mục tiêu' all: 'là những gì tôi mong đợi, thay vào đó. Tôi hy vọng OP sẽ trả lời ... – ph0t0n

Các vấn đề liên quan