[SOLVED] Compilation Error when using existing filenames from another project
-
I'm working in Windows 7 with Qt 5.3.1 and Qt Creator 3.1.2.
I have an existing project and I wanted to reuse parts of it.
I created a new project, and Added Existing Files: a certain .h and .cpp pair that I wanted to reuse.
For some reason, when compiling the new project, I get an error coming from Main.obj, stating that I am missing a certain include file - a file that is referenced in the main.cpp of the original project but definitely not in mine.
Both projects are doing Shadow Build, to different locations (in both cases, not to a folder on the level of the project folders but to another location).
I managed to reproduce this at least once with two new projects, one including a shared file from another. When I made sure that the original project's main was using something that the new project's main didn't have - I got the error.
Cleaning and Rebuilding didn't help.
-
Maybe I'll say something obvious, but did you check yours #include uses related path and not full path?
Have you been opening the 2 project in the same time in QtCreator? Did you check that QtCreator did not confuse the main.cpp files in the .pro file?
-
"obvious" is welcome :)
First off, I am working with the projects separately, right now only with the second one - the one that gives me the error.
Second, I don't even have an #include statement. All I did was to add the existing files into the project, without actually including any in my actual code.
I have a feeling like there's an old Main.obj file somewhere that is somehow made based on my first project, and anything I do with the second project is working with it - but I'm not sure how to get to the actual evidence/solution.
-
Additional information: if I change my main.cpp to another name, i.e. mymain.cpp - it compiles fine. Once I set it back to main.cpp , I have the linking error.
Here's my compile output (please ignore the bold parts, that's asterisks being read as bold by the forum site):
22:04:34: Starting: "C:\Qt5\Tools\QtCreator\bin\jom.exe"
C:\Qt5\Tools\QtCreator\bin\jom.exe -f Makefile.Debug
cl -c -nologo -Zm200 -Zc:wchar_t -Zi -MDd -GR -W3 -w34100 -w34189 -EHsc /Fddebug\SecondApp.pdb -DUNICODE -DWIN32 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I"C:\Qt5\5.3\msvc2010_opengl\include" -I"C:\Qt5\5.3\msvc2010_opengl\include\QtWidgets" -I"C:\Qt5\5.3\msvc2010_opengl\include\QtGui" -I"C:\Qt5\5.3\msvc2010_opengl\include\QtCore" -I"debug" -I"." -I"." -I"C:\Qt5\5.3\msvc2010_opengl\mkspecs\win32-msvc2010" -Fodebug\ @C:\Users\frank\AppData\Local\Temp\main.obj.10068.31.jom
main.cpp
echo 1 /* CREATEPROCESS_MANIFEST_RESOURCE_ID / 24 / RT_MANIFEST / "debug\SecondApp.exe.embed.manifest">debug\SecondApp.exe_manifest.rc
if not exist debug\SecondApp.exe if exist debug\SecondApp.exe.embed.manifest del debug\SecondApp.exe.embed.manifest
if exist debug\SecondApp.exe.embed.manifest copy /Y debug\SecondApp.exe.embed.manifest debug\SecondApp.exe_manifest.bak
1 file(s) copied.
link /NOLOGO /DYNAMICBASE /NXCOMPAT /DEBUG /SUBSYSTEM:WINDOWS "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='' processorArchitecture='*'" /MANIFEST /MANIFESTFILE:debug\SecondApp.exe.embed.manifest /OUT:debug\SecondApp.exe @C:\Users\frank\AppData\Local\Temp\SecondApp.exe.10068.2761.jommain.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall FirstMainWindow::~FirstMainWindow(void)" (??1FirstMainWindow@@UAE@XZ) referenced in function _main
main.obj : error LNK2019: unresolved external symbol "public: __thiscall FirstMainWindow::FirstMainWindow(class QWidget *)" (??0FirstMainWindow@@QAE@PAVQWidget@@@Z) referenced in function _main
debug\SecondApp.exe : fatal error LNK1120: 2 unresolved externals
I see a reference to
C:\Users\frank\AppData\Local\Temp\main.obj.10068.31.jom
but that location doesn't actually have that file or any main.obj files. -
Can you post your pro files? And tell us which cpp/h is the problem in the pro files.
-
The error I get is what I posted in the last comment - so it seems to be coming from a main.obj but not from any actual cpp/h file I'm looking at.
Here's my .pro files. Note that the FirstApp has a FirstMainWindow, and SecondApp has a MainWindow. Even though I'm linking the second application, I get the error about that FirstMainWindow.
TARGET = FirstApp
TEMPLATE = appSOURCES += main.cpp
usedinboth.cpp
firstmainwindow.cppHEADERS +=
usedinboth.h
firstmainwindow.hFORMS +=
firstmainwindow.uiSecondApp.pro:
TARGET = SecondApp
TEMPLATE = appSOURCES +=
mainwindow.cpp
../FirstApp/usedinboth.cpp
main.cppHEADERS += mainwindow.h
../FirstApp/usedinboth.hFORMS += mainwindow.ui
-
Hmm... Those are pretty edited pro files so I don't see anything wrong there.
How about try building just application 2 on the command line. Take Qt Creator out of the equation and do qmake/make on the command line. For mingw it would be:
- qmake
- mingw32-make
For MSVC, you would need a dev env command prompt:
- qmake
- nmake
In your first post you mentioned that the main.obj file referenced in the temp directory didn't exist. That means that it was built for that run. This means that it is using the code from main.cpp for app1 instead of app2. This means you more than likely have some kind of build issue that I can't see since I can't see Qt creator/real project files/or code. For some reason Qt Creator is choosing to build App1's main.cpp instead of app2's.
So test command line and see if it resolves, and then maybe you just need to delete your app.pro.user and start it over from the base pro file.
Sorry I can't help more, there just isn't enough information for me to see anything.
-
First of all, ambershark, thank you for your help.
I didn't edit out anything except the QT += core gui and the greaterThan lines. This is really as small a project as I could make to reproduce this.
So, what I see is that if I try qmake and nmake debug without any parameters, it works fine.
The problem I get when I try to change my destination:
qmake.exe -o D:\secondapp_build\Makefile
D:\MyApp\SVN\branches\Qt5\SecondApp\SecondApp.pro -r -spec win32-msvc2010 "CONFIG+=DEBUG"This creates the makefiles in the D:\secondapp_build destination. When I try to nmake these, I get the same linking error as before.
In fact, if I look at the D:\secondapp_build\debug version of main.obj in Notepad++ I even see that it contains an #include to the wrong version of Main.cpp
Now, looking at the difference in the makefile.debug files but not sure what to focus on.
Here are the implicit rules from the local (working) version:
####### Implicit rules.SUFFIXES: .c .cpp .cc .cxx
{debug}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\FirstApp}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\FirstApp}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\FirstApp}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\FirstApp}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<And here are those of the broken "remote" one:
####### Implicit rules.SUFFIXES: .c .cpp .cc .cxx
{debug}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{debug}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{.}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\SecondApp}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\SecondApp}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\SecondApp}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\SecondApp}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\FirstApp}.cpp{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\FirstApp}.cc{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\FirstApp}.cxx{debug}.obj::
$(CXX) -c $(CXXFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<{..\MyApp\SVN\branches\Qt5\FirstApp}.c{debug}.obj::
$(CC) -c $(CFLAGS) $(INCPATH) -Fodebug\ @<<
$<
<<Is there any other part of the makefiles I could bring up here?
And thanks again!
-
No problem, happy to help...
Anyway, I think I see the problem. When you specify the build directory the paths being set in the resulting makefile are causing main.cpp to be made into main.obj including the one in FirstApp.
Because the makefile is using object matching instead of specifying the files to build specifically it is getting confused. So it is building main.cpp from FirstApp after it builds it from SecondApp. This results in main.obj being the one from FirstApp as it overwrote the one from SecondApp.
There are a few solutions I would use for this:
-
Since you have an object you need in multiple projects consider making it a simple library with that object and any others you share. Then you can have each app include that lib and you're all set. No conflicts. Plus this has the added benefit of centralized code for that object without the confusion of code shared between applications.
-
Copy the "shared" code to the second app. You won't really be sharing here so any changes would have to be done in both copies of it. This is a hacky solution. #1 is much better idea for this.
-
You can try not specifying build directory on the command line but instead putting it into the project files, things like:
@
DESTDIR = ../debug-build-app2
MOC_DIR = ../debug-build-app2
OBJETS_DIR = ../debug-build-app2
UI_DIR = ../debug-build=app2
@That would put all your build in ../debug-build-app2.
Using this approach I would put in checks for debug versus release and name directories and stuff appropriately.
Anyway, I would honestly move to the library approach. Not only will it fix your problem but it is a much cleaner way to share code between applications. Much easier for maintenance too when someone other than you comes along to support the app. Or even you in the future if you forget that you are sharing code and such.
-
-
Thanks ambershark,
Definitely you helped me already by suggesting going outside Qt Creator.
I agree that the library approach is best - in fact that would be the longer term goal. But isn't the problem here the paths and the identical filenames? Meaning, if I had the same output directory, and a file named ClassA.cpp in both my new project and in the other project (regardless of whether it is a library or an application) - wouldn't I get the same issue with the .obj of this file?
I think for now I will either try your suggestion #3, or stick to my very basic workaround: just making sure my new project doesn't use the same filenames as the existing one (i.e. replacing main.cpp with mymain.cpp).
I think I can mark this one as SOLVED - but I wonder, if I really manage to reproduce it another time with another minimal project - maybe this qualifies as a QMAKE bug.
-
Yea the problem is the makefile. I'm not sure I would blame qt because it's more of a make issue. When qt generates the makefile they are using @<< and $< for matching of objects to build. So in the implicit rules the make file builds any cpp file that it finds in the directory matching the pattern.
So since it knows it needs to build main.cpp when it sees it in 2nd app dir it builds it. And when it sees it again in 1st app dir it builds it again overwriting the one you actually wanted.
This is what looks like is happening. I'm not 100% sure but that is how I'm reading those makefiles. Been a really long time since I wrote my own makefile though. :-)