diff options
Diffstat (limited to 'qmake')
49 files changed, 7322 insertions, 3254 deletions
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index d4f5849e90..8d56fc8d0f 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -9,10 +9,9 @@ LFLAGS = @QMAKE_LFLAGS@ OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \ mingw_make.o option.o winmakefile.o projectgenerator.o \ meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \ - borland_bmake.o msvc_dsp.o msvc_vcproj.o msvc_nmake.o msvc_objectmodel.o \ + borland_bmake.o msvc_vcproj.o msvc_vcxproj.o msvc_nmake.o msvc_objectmodel.o msbuild_objectmodel.o \ symmake.o initprojectdeploy_symbian.o symmake_abld.o symmake_sbsv2.o \ - registry.o \ - epocroot.o + symbiancommon.o registry.o epocroot.o #qt code QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \ @@ -32,11 +31,12 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge generators/unix/unixmake.cpp generators/win32/winmakefile.cpp generators/projectgenerator.cpp \ generators/mac/pbuilder_pbx.cpp generators/mac/xmloutput.cpp generators/metamakefile.cpp \ generators/makefiledeps.cpp option.cpp generators/win32/mingw_make.cpp generators/makefile.cpp \ - generators/win32/msvc_objectmodel.cpp generators/win32/msvc_nmake.cpp generators/win32/borland_bmake.cpp \ + generators/win32/msvc_vcproj.cpp generators/win32/msvc_vcxproj.cpp generators/win32/msvc_objectmodel.cpp generators/win32/msbuild_objectmodel.cpp generators/win32/msbuild_objectmodel.cpp generators/win32/msvc_nmake.cpp generators/win32/borland_bmake.cpp \ generators/symbian/symmake.cpp generators/symbian/initprojectdeploy_symbian.cpp \ $(SOURCE_PATH)/tools/shared/windows/registry.cpp \ $(SOURCE_PATH)/tools/shared/symbian/epocroot.cpp \ generators/symbian/symmake_abld.cpp generators/symbian/symmake_sbsv2.cpp \ + generaters/symbian/symbiancommon.cpp \ $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \ $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ @@ -235,7 +235,7 @@ option.o: option.cpp option.h $(BUILD_PATH)/src/corelib/global/qconfig.cpp qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp -metamakefile.o: generators/metamakefile.cpp +metamakefile.o: generators/metamakefile.cpp generators/symbian/symbian_makefile.h $(CXX) -c -o $@ $(CXXFLAGS) generators/metamakefile.cpp xmloutput.o: generators/xmloutput.cpp @@ -265,15 +265,18 @@ msvc_objectmodel.o: generators/win32/msvc_objectmodel.cpp msvc_vcproj.o: generators/win32/msvc_vcproj.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_vcproj.cpp +msbuild_objectmodel.o: generators/win32/msbuild_objectmodel.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msbuild_objectmodel.cpp + +msvc_vcxproj.o: generators/win32/msvc_vcxproj.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_vcxproj.cpp + msvc_nmake.o: generators/win32/msvc_nmake.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_nmake.cpp pbuilder_pbx.o: generators/mac/pbuilder_pbx.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp -msvc_dsp.o: generators/win32/msvc_dsp.cpp - $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_dsp.cpp - symmake.o: generators/symbian/symmake.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/symbian/symmake.cpp @@ -283,6 +286,9 @@ symmake_abld.o: generators/symbian/symmake_abld.cpp symmake_sbsv2.o: generators/symbian/symmake_sbsv2.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/symbian/symmake_sbsv2.cpp +symbiancommon.o: generators/symbian/symbiancommon.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/symbian/symbiancommon.cpp + initprojectdeploy_symbian.o: generators/symbian/initprojectdeploy_symbian.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/symbian/initprojectdeploy_symbian.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index c452c5ab25..4d0121c02b 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -1,4 +1,4 @@ -!IF "$(QMAKESPEC)" == "win32-msvc" || "$(QMAKESPEC)" == "win32-msvc.net" || "$(QMAKESPEC)" == "win32-msvc2002" || "$(QMAKESPEC)" == "win32-msvc2003" || "$(QMAKESPEC)" == "win32-msvc2005" || "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-icc" +!IF "$(QMAKESPEC)" == "win32-msvc" || "$(QMAKESPEC)" == "win32-msvc.net" || "$(QMAKESPEC)" == "win32-msvc2002" || "$(QMAKESPEC)" == "win32-msvc2003" || "$(QMAKESPEC)" == "win32-msvc2005" || "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-msvc2010" || "$(QMAKESPEC)" == "win32-icc" !if "$(SOURCE_PATH)" == "" SOURCE_PATH = .. @@ -23,11 +23,14 @@ LINK = link # specific stuff for VS2005 # !if "$(QMAKESPEC)" == "win32-msvc2005" -CFLAGS = /Zc:wchar_t- +CFLAGS_EXTRA = /Zc:wchar_t- +!elseif "$(QMAKESPEC)" == "win32-msvc2008" || "$(QMAKESPEC)" == "win32-msvc2010" +CFLAGS_EXTRA = /MP !endif -CFLAGS = -c -Fo$@ \ +CFLAGS_BARE = -c -Fo./ \ -W3 -nologo -O2 \ + $(CFLAGS_EXTRA) \ -I. -Igenerators -Igenerators\unix -Igenerators\win32 -Igenerators\mac -Igenerators\symbian \ -I$(BUILD_PATH)\include -I$(BUILD_PATH)\include\QtCore \ -I$(SOURCE_PATH)\include -I$(SOURCE_PATH)\include\QtCore \ @@ -37,49 +40,28 @@ CFLAGS = -c -Fo$@ \ -I$(SOURCE_PATH)\tools\shared \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NODLL -DQT_NO_STL \ -DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP -DQT_BUILD_QMAKE -DQT_NO_THREAD \ - -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM -DQT_NO_PCRE -DQT_BOOTSTRAPPED \ - $(CFLAGS) -CXXFLAGS = $(CFLAGS) + -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM -DQT_NO_PCRE -DQT_BOOTSTRAPPED +CFLAGS = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch $(CFLAGS_BARE) $(CFLAGS) + +CXXFLAGS_BARE = $(CFLAGS_BARE) +CXXFLAGS = $(CFLAGS) + LFLAGS = LIBS = ole32.lib advapi32.lib LINKQMAKE = $(LINK) $(LFLAGS) -OUT:qmake.exe $(OBJS) $(QTOBJS) $(LIBS) ADDCLEAN = vc60.pdb vc70.pdb qmake.pdb qmake.ilk -!ELSE -# -# specific stuff for Borland make -# -!if !$d(BCB) -BCB = $(MAKEDIR)\.. -!endif -CXX = bcc32 -CFLAGS = -c -o$@ \ - -tWR -w -w-hid -w-use -O1 \ - -I. -Igenerators -Igenerators\unix -Igenerators\win32 -Igenerators\mac -Igenerators\symbian \ - -I$(BUILD_PATH)\include -I$(BUILD_PATH)\include\QtCore \ - -I$(SOURCE_PATH)\include -I$(SOURCE_PATH)\include\QtCore \ - -I$(BUILD_PATH)\src\corelib\global \ - -I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \ - -I$(SOURCE_PATH)\tools\shared \ - -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NODLL -DQT_NO_STL \ - -DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP -DQT_BUILD_QMAKE -DQT_NO_THREAD \ - -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -CXXFLAGS = $(CFLAGS) -LFLAGS = -L$(BCB)\lib -c -x -Gn -ap -Tpe c0x32.obj -LIBS = import32.lib cw32i.lib -LINKQMAKE = ilink32 $(LFLAGS) $(OBJS) $(QTOBJS), qmake.exe,,$(LIBS) -ADDCLEAN = qmake.tds +!ELSE +!ERROR Unsupported compiler for this Makefile !ENDIF #qmake code OBJS = project.obj main.obj makefile.obj unixmake.obj unixmake2.obj mingw_make.obj \ option.obj winmakefile.obj projectgenerator.obj property.obj meta.obj \ makefiledeps.obj metamakefile.obj xmloutput.obj pbuilder_pbx.obj \ - borland_bmake.obj msvc_nmake.obj msvc_dsp.obj msvc_vcproj.obj \ - msvc_objectmodel.obj symmake.obj initprojectdeploy_symbian.obj \ - registry.obj \ - epocroot.obj \ - symmake_abld.obj symmake_sbsv2.obj + borland_bmake.obj msvc_nmake.obj msvc_vcproj.obj msvc_vcxproj.obj \ + msvc_objectmodel.obj msbuild_objectmodel.obj symmake.obj initprojectdeploy_symbian.obj \ + symmake_abld.obj symmake_sbsv2.obj symbiancommon.obj registry.obj epocroot.obj !IFDEF QMAKE_OPENSOURCE_EDITION CFLAGS = $(CFLAGS) -DQMAKE_OPENSOURCE_EDITION @@ -136,80 +118,15 @@ QTOBJS= \ first all: qmake.exe qmake.exe: $(OBJS) $(QTOBJS) - $(LINKQMAKE) + $(LINKQMAKE) qmake_pch.obj -copy qmake.exe $(BUILD_PATH)\bin\qmake.exe clean:: - -del qbitarray.obj - -del qbuffer.obj - -del qcryptographichash.obj - -del qlinkedlist.obj - -del qfsfileengine.obj - -del qfsfileengine_iterator.obj - -del qbytearray.obj - -del qvsnprintf.obj - -del qbytearraymatcher.obj - -del qdatetime.obj - -del qdir.obj - -del qdiriterator.obj - -del qfile.obj - -del qtemporaryfile.obj - -del qabstractfileengine.obj - -del qfsfileengine_win.obj + -del $(QTOBJS) + -del $(OBJS) + -del qmake_pch.obj + -del qmake_pch.pch -del qsystemlibrary.obj - -del qfsfileengine_iterator_win.obj - -del qfileinfo.obj - -del qglobal.obj - -del qhash.obj - -del qiodevice.obj - -del qlist.obj - -del qlocale.obj - -del qmalloc.obj - -del qmap.obj - -del qregexp.obj - -del qtextcodec.obj - -del qutfcodec.obj - -del qstring.obj - -del qstringlist.obj - -del qtextstream.obj - -del qdatastream.obj - -del quuid.obj - -del qvector.obj - -del qsettings.obj - -del qlibraryinfo.obj - -del qvariant.obj - -del qurl.obj - -del qsettings_win.obj - -del qmetatype.obj - -del project.obj - -del main.obj - -del makefile.obj - -del unixmake.obj - -del unixmake2.obj - -del mingw_make.obj - -del option.obj - -del winmakefile.obj - -del projectgenerator.obj - -del property.obj - -del meta.obj - -del makefiledeps.obj - -del metamakefile.obj - -del xmloutput.obj - -del borland_bmake.obj - -del msvc_nmake.obj - -del msvc_dsp.obj - -del msvc_vcproj.obj - -del msvc_objectmodel.obj - -del symmake.obj - -del symmake_abld.obj - -del symmake_sbsv2.obj - -del initprojectdeploy_symbian.obj - -del registry.obj - -del epocroot.obj - -del pbuilder_pbx.obj - -del qxmlstream.obj - -del qxmlutils.obj - -del qnumeric.obj -del vc60.pdb -del vc70.pdb -del qmake.pdb @@ -231,224 +148,60 @@ distclean:: clean .cxx.obj: $(CXX) $(CXXFLAGS) $< -qsettings_win.obj: $(SOURCE_PATH)\src\corelib\io\qsettings_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qsettings_win.cpp - -qsettings.obj: $(SOURCE_PATH)\src\corelib\io\qsettings.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qsettings.cpp - -qlibraryinfo.obj: $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp - -qnumeric.obj: $(SOURCE_PATH)\src\corelib\global\qnumeric.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\global\qnumeric.cpp - -qvariant.obj: $(SOURCE_PATH)\src\corelib\kernel\qvariant.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\kernel\qvariant.cpp - -qurl.obj: $(SOURCE_PATH)\src\corelib\io\qurl.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qurl.cpp - -qtextstream.obj: $(SOURCE_PATH)\src\corelib\io\qtextstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qtextstream.cpp - -qdatastream.obj: $(SOURCE_PATH)\src\corelib\io\qdatastream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qdatastream.cpp - -qiodevice.obj: $(SOURCE_PATH)\src\corelib\io\qiodevice.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qiodevice.cpp - -qmalloc.obj: $(SOURCE_PATH)\src\corelib\global\qmalloc.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\global\qmalloc.cpp - -qglobal.obj: $(SOURCE_PATH)\src\corelib\global\qglobal.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\global\qglobal.cpp - -qhash.obj: $(SOURCE_PATH)\src\corelib\tools\qhash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qhash.cpp - -qbytearray.obj: $(SOURCE_PATH)\src\corelib\tools\qbytearray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qbytearray.cpp - -qcryptographichash.obj: $(SOURCE_PATH)\src\corelib\tools\qcryptographichash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qcryptographichash.cpp - -qvsnprintf.obj: $(SOURCE_PATH)\src\corelib\tools\qvsnprintf.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qvsnprintf.cpp - -qbytearraymatcher.obj: $(SOURCE_PATH)\src\corelib\tools\qbytearraymatcher.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qbytearraymatcher.cpp - -qchar.obj: $(SOURCE_PATH)\src\corelib\tools\qchar.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qchar.cpp - -qutfcodec.obj: $(SOURCE_PATH)\src\corelib\codecs\qutfcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\codecs\qutfcodec.cpp - -qstring.obj: $(SOURCE_PATH)\src\corelib\tools\qstring.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qstring.cpp - -qstringmatcher.obj: $(SOURCE_PATH)\src\corelib\tools\qstringmatcher.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qstringmatcher.cpp - -qlocale.obj: $(SOURCE_PATH)\src\corelib\tools\qlocale.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qlocale.cpp - -quuid.obj: $(SOURCE_PATH)\src\corelib\plugin\quuid.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\plugin\quuid.cpp - -qbuffer.obj: $(SOURCE_PATH)\src\corelib\io\qbuffer.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qbuffer.cpp - -qlist.obj: $(SOURCE_PATH)\src\corelib\tools\qlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qlist.cpp - -qlinkedlist.obj: $(SOURCE_PATH)\src\corelib\tools\qlinkedlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qlinkedlist.cpp - -qfile.obj: $(SOURCE_PATH)\src\corelib\io\qfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfile.cpp - -qtemporaryfile.obj: $(SOURCE_PATH)\src\corelib\io\qtemporaryfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qtemporaryfile.cpp - -qfsfileengine_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_win.cpp +$(OBJS): qmake_pch.obj qsystemlibrary.obj: $(SOURCE_PATH)\src\corelib\plugin\qsystemlibrary.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\plugin\qsystemlibrary.cpp -qfsfileengine_iterator_win.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator_win.cpp - -qfsfileengine.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine.cpp - -qfsfileengine_iterator.obj: $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfsfileengine_iterator.cpp - -qabstractfileengine.obj: $(SOURCE_PATH)\src\corelib\io\qabstractfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qabstractfileengine.cpp - -qtextcodec.obj: $(SOURCE_PATH)\src\corelib\codecs\qtextcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\codecs\qtextcodec.cpp - -qregexp.obj: $(SOURCE_PATH)\src\corelib\tools\qregexp.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qregexp.cpp +$(QTOBJS): qmake_pch.obj -qvector.obj: $(SOURCE_PATH)\src\corelib\tools\qvector.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qvector.cpp +qmake_pch.obj: + $(CXX) $(CXXFLAGS_BARE) -c -Yc -Fpqmake_pch.pch -TP qmake_pch.h -qbitarray.obj: $(SOURCE_PATH)\src\corelib\tools\qbitarray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qbitarray.cpp - -qdir.obj: $(SOURCE_PATH)\src\corelib\io\qdir.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qdir.cpp - -qdiriterator.obj: $(SOURCE_PATH)\src\corelib\io\qdiriterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qdiriterator.cpp - -qmetatype.obj: $(SOURCE_PATH)\src\corelib\kernel\qmetatype.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\kernel\qmetatype.cpp - -qfileinfo.obj: $(SOURCE_PATH)\src\corelib\io\qfileinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\io\qfileinfo.cpp - -qdatetime.obj: $(SOURCE_PATH)\src\corelib\tools\qdatetime.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qdatetime.cpp - -qstringlist.obj: $(SOURCE_PATH)\src\corelib\tools\qstringlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qstringlist.cpp - -qmap.obj: $(SOURCE_PATH)\src\corelib\tools\qmap.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qmap.cpp - -qunicodetables.obj: $(SOURCE_PATH)\src\corelib\tools\qunicodetables.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\tools\qunicodetables.cpp - -makefile.obj: $(SOURCE_PATH)/qmake/generators\makefile.cpp - $(CXX) $(CXXFLAGS) generators\makefile.cpp - -unixmake.obj: $(SOURCE_PATH)/qmake/generators\unix\unixmake.cpp - $(CXX) $(CXXFLAGS) generators\unix\unixmake.cpp - -unixmake2.obj: $(SOURCE_PATH)/qmake/generators\unix\unixmake2.cpp - $(CXX) $(CXXFLAGS) generators\unix\unixmake2.cpp - -winmakefile.obj: $(SOURCE_PATH)/qmake/generators/win32/winmakefile.cpp - $(CXX) $(CXXFLAGS) generators/win32/winmakefile.cpp - -borland_bmake.obj: $(SOURCE_PATH)/qmake/generators/win32/borland_bmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/borland_bmake.cpp - -mingw_make.obj: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp - $(CXX) $(CXXFLAGS) generators/win32/mingw_make.cpp - -msvc_nmake.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp - -msvc_dsp.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp - -msvc_vcproj.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp - -msvc_objectmodel.obj: $(SOURCE_PATH)/qmake/generators/win32/msvc_objectmodel.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp - -symmake.obj: $(SOURCE_PATH)/qmake/generators/symbian/symmake.cpp - $(CXX) $(CXXFLAGS) generators/symbian/symmake.cpp - -symmake_abld.obj: $(SOURCE_PATH)/qmake/generators/symbian/symmake_abld.cpp - $(CXX) $(CXXFLAGS) generators/symbian/symmake_abld.cpp - -symmake_sbsv2.obj: $(SOURCE_PATH)/qmake/generators/symbian/symmake_sbsv2.cpp - $(CXX) $(CXXFLAGS) generators/symbian/symmake_sbsv2.cpp - -initprojectdeploy_symbian.obj: $(SOURCE_PATH)/qmake/generators/symbian/initprojectdeploy_symbian.cpp - $(CXX) $(CXXFLAGS) generators/symbian/initprojectdeploy_symbian.cpp +{$(SOURCE_PATH)\qmake\generators\mac}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -registry.obj: $(SOURCE_PATH)/tools/shared/windows/registry.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/tools/shared/windows/registry.cpp +{$(SOURCE_PATH)\qmake\generators\symbian}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -epocroot.obj: $(SOURCE_PATH)/tools/shared/symbian/epocroot.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/tools/shared/symbian/epocroot.cpp +{$(SOURCE_PATH)\qmake\generators\unix}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -md5.obj: $(SOURCE_PATH)\src\3rdparty\md5\md5.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\3rdparty\md5\md5.cpp +{$(SOURCE_PATH)\qmake\generators\win32}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -project.obj: $(SOURCE_PATH)/qmake/project.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) project.cpp +{$(SOURCE_PATH)\qmake\generators}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -meta.obj: $(SOURCE_PATH)/qmake/meta.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) meta.cpp +{$(SOURCE_PATH)\qmake}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -main.obj: $(SOURCE_PATH)/qmake/main.cpp $(SOURCE_PATH)/qmake/project.h - $(CXX) $(CXXFLAGS) main.cpp +{$(SOURCE_PATH)\src\3rdparty\md5}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -option.obj: $(SOURCE_PATH)/qmake/option.cpp $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) option.cpp +{$(SOURCE_PATH)\src\corelib\codecs}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -property.obj: $(SOURCE_PATH)/qmake/property.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) property.cpp +{$(SOURCE_PATH)\src\corelib\global}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -projectgenerator.obj: $(SOURCE_PATH)/qmake/generators/projectgenerator.cpp - $(CXX) $(CXXFLAGS) generators/projectgenerator.cpp +{$(SOURCE_PATH)\src\corelib\io}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -pbuilder_pbx.obj: $(SOURCE_PATH)/qmake/generators/mac/pbuilder_pbx.cpp - $(CXX) $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp +{$(SOURCE_PATH)\src\corelib\kernel}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -makefiledeps.obj: $(SOURCE_PATH)/qmake/generators/makefiledeps.cpp - $(CXX) $(CXXFLAGS) generators/makefiledeps.cpp +{$(SOURCE_PATH)\src\corelib\plugin}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -metamakefile.obj: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp - $(CXX) $(CXXFLAGS) generators/metamakefile.cpp +{$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -xmloutput.obj: $(SOURCE_PATH)/qmake/generators/xmloutput.cpp - $(CXX) $(CXXFLAGS) generators/xmloutput.cpp +{$(SOURCE_PATH)\src\corelib\xml}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -qxmlstream.obj: $(SOURCE_PATH)\src\corelib\xml\qxmlstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\xml\qxmlstream.cpp +{$(SOURCE_PATH)\tools\shared\symbian}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< -qxmlutils.obj: $(SOURCE_PATH)\src\corelib\xml\qxmlutils.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)\src\corelib\xml\qxmlutils.cpp +{$(SOURCE_PATH)\tools\shared\windows}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 5b5915489c..f313f9ef0b 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -27,7 +27,7 @@ CFLAGS = -c -o$@ -O \ -DQT_BUILD_QMAKE -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ -DQT_BOOTSTRAPPED CXXFLAGS = $(CFLAGS) -LFLAGS = +LFLAGS = -static-libgcc -static-libstdc++ -s LIBS = -lole32 -luuid LINKQMAKE = g++ $(LFLAGS) -o qmake.exe $(OBJS) $(QTOBJS) $(LIBS) ADDCLEAN = @@ -37,11 +37,9 @@ ADDCLEAN = OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \ option.o winmakefile.o projectgenerator.o property.o meta.o \ makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \ - borland_bmake.o msvc_nmake.o msvc_dsp.o msvc_vcproj.o \ - msvc_objectmodel.o symmake.o initprojectdeploy_symbian.o \ - registry.o \ - epocroot.o \ - symmake_abld.o symmake_sbsv2.o + borland_bmake.o msvc_nmake.o msvc_vcproj.o msvc_vcxproj.o \ + msvc_objectmodel.o msbuild_objectmodel.o symmake.o initprojectdeploy_symbian.o \ + symmake_abld.o symmake_sbsv2.o symbiancommon.o registry.o epocroot.o ifdef QMAKE_OPENSOURCE_EDITION CFLAGS += -DQMAKE_OPENSOURCE_EDITION @@ -264,15 +262,18 @@ mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp -msvc_dsp.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp - msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp msvc_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_objectmodel.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp +msvc_vcxproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcxproj.cpp + $(CXX) $(CXXFLAGS) generators/win32/msvc_vcxproj.cpp + +msbuild_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msbuild_objectmodel.cpp + $(CXX) $(CXXFLAGS) generators/win32/msbuild_objectmodel.cpp + symmake.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake.cpp $(CXX) $(CXXFLAGS) generators/symbian/symmake.cpp @@ -282,6 +283,9 @@ symmake_abld.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake_abld.cpp symmake_sbsv2.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake_sbsv2.cpp $(CXX) $(CXXFLAGS) generators/symbian/symmake_sbsv2.cpp +symbiancommon.o: $(SOURCE_PATH)/qmake/generators/symbian/symbiancommon.cpp + $(CXX) $(CXXFLAGS) generators/symbian/symbiancommon.cpp + initprojectdeploy_symbian.o: $(SOURCE_PATH)/qmake/generators/symbian/initprojectdeploy_symbian.cpp $(CXX) $(CXXFLAGS) generators/symbian/initprojectdeploy_symbian.cpp @@ -315,7 +319,7 @@ pbuilder_pbx.o: $(SOURCE_PATH)/qmake/generators/mac/pbuilder_pbx.cpp makefiledeps.o: $(SOURCE_PATH)/qmake/generators/makefiledeps.cpp $(CXX) $(CXXFLAGS) generators/makefiledeps.cpp -metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp +metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp $(SOURCE_PATH)/qmake/generators/symbian/symbian_makefile.h $(CXX) $(CXXFLAGS) generators/metamakefile.cpp xmloutput.o: $(SOURCE_PATH)/qmake/generators/xmloutput.cpp @@ -326,3 +330,4 @@ qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp + diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh index 5295ddbbf1..af5428877d 100644 --- a/qmake/Makefile.win32-g++-sh +++ b/qmake/Makefile.win32-g++-sh @@ -27,7 +27,7 @@ CFLAGS = -c -o$@ -O \ -DQT_BUILD_QMAKE -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ -DQT_BOOTSTRAPPED CXXFLAGS = $(CFLAGS) -LFLAGS = +LFLAGS = -static-libgcc -static-libstdc++ -s LIBS = -lole32 -luuid LINKQMAKE = g++ $(LFLAGS) -o qmake.exe $(OBJS) $(QTOBJS) $(LIBS) ADDCLEAN = @@ -37,11 +37,9 @@ ADDCLEAN = OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \ option.o winmakefile.o projectgenerator.o property.o meta.o \ makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \ - borland_bmake.o msvc_nmake.o msvc_dsp.o msvc_vcproj.o \ - msvc_objectmodel.o symmake.o initprojectdeploy_symbian.o \ - registry.o \ - epocroot.o \ - symmake_abld.o symmake_sbsv2.o + borland_bmake.o msvc_nmake.o msvc_vcproj.o msvc_vcxproj.o \ + msvc_objectmodel.o msbuild_objectmodel.o symmake.o initprojectdeploy_symbian.o \ + symmake_abld.o symmake_sbsv2.o symbiancommon.o registry.o epocroot.o ifdef QMAKE_OPENSOURCE_EDITION CFLAGS += -DQMAKE_OPENSOURCE_EDITION @@ -263,15 +261,18 @@ mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp -msvc_dsp.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_dsp.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_dsp.cpp - msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp msvc_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_objectmodel.cpp $(CXX) $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp +msvc_vcxproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcxproj.cpp + $(CXX) $(CXXFLAGS) generators/win32/msvc_vcxproj.cpp + +msbuild_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msbuild_objectmodel.cpp + $(CXX) $(CXXFLAGS) generators/win32/msbuild_objectmodel.cpp + symmake.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake.cpp $(CXX) $(CXXFLAGS) generators/symbian/symmake.cpp @@ -281,6 +282,9 @@ symmake_abld.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake_abld.cpp symmake_sbsv2.o: $(SOURCE_PATH)/qmake/generators/symbian/symmake_sbsv2.cpp $(CXX) $(CXXFLAGS) generators/symbian/symmake_sbsv2.cpp +symbiancommon.o: $(SOURCE_PATH)/qmake/generators/symbian/symbiancommon.cpp + $(CXX) $(CXXFLAGS) generators/symbian/symbiancommon.cpp + initprojectdeploy_symbian.o: $(SOURCE_PATH)/qmake/generators/symbian/initprojectdeploy_symbian.cpp $(CXX) $(CXXFLAGS) generators/symbian/initprojectdeploy_symbian.cpp @@ -314,7 +318,7 @@ pbuilder_pbx.o: $(SOURCE_PATH)/qmake/generators/mac/pbuilder_pbx.cpp makefiledeps.o: $(SOURCE_PATH)/qmake/generators/makefiledeps.cpp $(CXX) $(CXXFLAGS) generators/makefiledeps.cpp -metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp +metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp $(SOURCE_PATH)/qmake/generators/symbian/symbian_makefile.h $(CXX) $(CXXFLAGS) generators/metamakefile.cpp xmloutput.o: $(SOURCE_PATH)/qmake/generators/xmloutput.cpp diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 4e9703fe21..aa55f5119d 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -523,9 +523,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData()); QTextStream mkt(&mkf); writeHeader(mkt); - mkt << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? - QString((QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake")) : - var("QMAKE_QMAKE")) << endl; + mkt << "QMAKE = " << var("QMAKE_QMAKE") << endl; writeMakeQmake(mkt); mkt.flush(); mkf.close(); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 5ec47ecc1f..c7b147398b 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -466,14 +466,37 @@ MakefileGenerator::init() if(!project->isEmpty("QMAKE_SUBSTITUTES")) { const QStringList &subs = v["QMAKE_SUBSTITUTES"]; for(int i = 0; i < subs.size(); ++i) { - if(!subs.at(i).endsWith(".in")) { - warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'", - subs.at(i).toLatin1().constData()); - continue; + QString inn = subs.at(i) + ".input", outn = subs.at(i) + ".output"; + if (v.contains(inn) || v.contains(outn)) { + if (!v.contains(inn) || !v.contains(outn)) { + warn_msg(WarnLogic, "Substitute '%s' has only one of .input and .output", + subs.at(i).toLatin1().constData()); + continue; + } + const QStringList &tinn = v[inn], &toutn = v[outn]; + if (tinn.length() != 1) { + warn_msg(WarnLogic, "Substitute '%s.input' does not have exactly one value", + subs.at(i).toLatin1().constData()); + continue; + } + if (toutn.length() != 1) { + warn_msg(WarnLogic, "Substitute '%s.output' does not have exactly one value", + subs.at(i).toLatin1().constData()); + continue; + } + inn = tinn.first(); + outn = toutn.first(); + } else { + inn = subs.at(i); + if(!inn.endsWith(".in")) { + warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'", + inn.toLatin1().constData()); + continue; + } + outn = inn.left(inn.length()-3); } - QFile in(fileFixify(subs.at(i))), out(fileInfo(subs.at(i)).fileName()); - if(out.fileName().endsWith(".in")) - out.setFileName(out.fileName().left(out.fileName().length()-3)); + QFile in(fileFixify(inn)); + QFile out(fileFixify(outn, qmake_getpwd(), Option::output_dir)); if(in.open(QFile::ReadOnly)) { QString contents; QStack<int> state; @@ -528,7 +551,7 @@ MakefileGenerator::init() if(out.exists() && out.open(QFile::ReadOnly)) { QString old = QString::fromUtf8(out.readAll()); if(contents == old) { - v["QMAKE_INTERNAL_INCLUDED_FILES"].append(subs.at(i)); + v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName()); continue; } out.close(); @@ -538,8 +561,9 @@ MakefileGenerator::init() continue; } } + mkdir(QFileInfo(out).absolutePath()); if(out.open(QFile::WriteOnly)) { - v["QMAKE_INTERNAL_INCLUDED_FILES"].append(subs.at(i)); + v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName()); out.write(contents.toUtf8()); } else { warn_msg(WarnLogic, "Cannot open substitute for output '%s'", @@ -806,9 +830,8 @@ MakefileGenerator::init() } // escape qmake command - if (!project->isEmpty("QMAKE_QMAKE")) { - project->values("QMAKE_QMAKE") = escapeFilePaths(project->values("QMAKE_QMAKE")); - } + QStringList &qmk = project->values("QMAKE_QMAKE"); + qmk = escapeFilePaths(qmk); } bool @@ -973,7 +996,7 @@ MakefileGenerator::writePrlFile(QTextStream &t) libs << "QMAKE_LIBS_PRIVATE"; t << "QMAKE_PRL_LIBS = "; for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it) - t << project->values((*it)).join(" ") << " "; + t << project->values((*it)).join(" ").replace('\\', "\\\\") << " "; t << endl; } } @@ -1246,7 +1269,8 @@ MakefileGenerator::writeInstalls(QTextStream &t, const QString &installs, bool n } if(!dirstr.endsWith(Option::dir_sep)) dirstr += Option::dir_sep; - if(exists(wild)) { //real file + bool is_target = (wild == fileFixify(var("TARGET"), FileFixifyAbsolute)); + if(is_target || exists(wild)) { //real file or target QString file = wild; QFileInfo fi(fileInfo(wild)); if(!target.isEmpty()) @@ -1260,7 +1284,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, const QString &installs, bool n QString cmd; if (fi.isDir()) cmd = "-$(INSTALL_DIR)"; - else if (fi.isExecutable()) + else if (is_target || fi.isExecutable()) cmd = "-$(INSTALL_PROGRAM)"; else cmd = "-$(INSTALL_FILE)"; @@ -1756,6 +1780,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) } QStringList tmp_dep = project->values((*it) + ".depends"); QString tmp_dep_cmd; + QString dep_cd_cmd; if(!project->isEmpty((*it) + ".depend_command")) { int argv0 = -1; QStringList cmdline = project->values((*it) + ".depend_command"); @@ -1774,6 +1799,9 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) cmdline[argv0] = escapeFilePath(cmdline.at(argv0)); } } + dep_cd_cmd = QLatin1String("cd ") + + escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false)) + + QLatin1String(" && "); } QStringList &vars = project->values((*it) + ".variables"); if(tmp_out.isEmpty() || tmp_cmd.isEmpty()) @@ -1821,8 +1849,6 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) tmp_clean = tmp_out; if(tmp_clean.indexOf("${QMAKE_") == -1) { t << "\n\t" << "-$(DEL_FILE) " << tmp_clean; - if (isForSymbian()) - t << " 2> NUL"; // Eliminate unnecessary warnings wrote_clean = true; } if(!wrote_clean_cmds || !wrote_clean) { @@ -1850,12 +1876,8 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) cleans.append(files); } } - if(!cleans.isEmpty()) { - if (isForSymbian()) - t << valGlue(cleans, "\n\t" + del_statement, " 2> NUL\n\t" + del_statement, " 2> NUL"); - else - t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, ""); - } + if(!cleans.isEmpty()) + t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, ""); if(!wrote_clean_cmds) { for(QStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) { t << "\n\t" << replaceExtraCompilerVariables(tmp_clean_cmds, (*input), @@ -1881,7 +1903,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) char buff[256]; QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, (*input), tmp_out); - dep_cmd = fixEnvVariables(dep_cmd); + dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd); if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { QString indeps; while(!feof(proc)) { @@ -1979,7 +2001,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) if(!tmp_dep_cmd.isEmpty() && doDepends()) { char buff[256]; QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, (*input), out); - dep_cmd = fixEnvVariables(dep_cmd); + dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd); if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { QString indeps; while(!feof(proc)) { @@ -2116,7 +2138,7 @@ MakefileGenerator::writeExtraVariables(QTextStream &t) bool MakefileGenerator::writeStubMakefile(QTextStream &t) { - t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; QStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; @@ -2171,14 +2193,14 @@ QString MakefileGenerator::buildArgs(const QString &outdir) ret += " -nodependheuristics"; if(!Option::mkfile::qmakespec_commandline.isEmpty()) ret += " -spec " + specdir(outdir); - if(Option::target_mode == Option::TARG_MAC9_MODE) - ret += " -mac9"; - else if(Option::target_mode == Option::TARG_MACX_MODE) - ret += " -macx"; - else if(Option::target_mode == Option::TARG_UNIX_MODE) - ret += " -unix"; - else if(Option::target_mode == Option::TARG_WIN_MODE) - ret += " -win32"; + if (Option::target_mode_overridden) { + if (Option::target_mode == Option::TARG_MACX_MODE) + ret += " -macx"; + else if (Option::target_mode == Option::TARG_UNIX_MODE) + ret += " -unix"; + else if (Option::target_mode == Option::TARG_WIN_MODE) + ret += " -win32"; + } //configs for(QStringList::Iterator it = Option::user_configs.begin(); @@ -2231,8 +2253,7 @@ MakefileGenerator::writeHeader(QTextStream &t) t << "# Project: " << fileFixify(project->projectFile()) << endl; t << "# Template: " << var("TEMPLATE") << endl; if(!project->isActiveConfig("build_pass")) - t << "# Command: " << build_args().replace("$(QMAKE)", - (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE"))) << endl; + t << "# Command: " << build_args().replace("$(QMAKE)", var("QMAKE_QMAKE")) << endl; t << "#############################################################################" << endl; t << endl; } @@ -2365,7 +2386,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT t << "MAKEFILE = " << ofile << endl; /* Calling Option::fixPathToTargetOS() is necessary for MinGW/MSYS, which requires * back-slashes to be turned into slashes. */ - t << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; t << "MKDIR = " << var("QMAKE_MKDIR") << endl; @@ -2688,8 +2709,6 @@ MakefileGenerator::writeMakeQmake(QTextStream &t) if(!specdir().isEmpty()) { if(exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"qmake.conf"))) t << escapeDependencyPath(specdir() + Option::dir_sep + "qmake.conf") << " "; - else if(exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"tmake.conf"))) - t << escapeDependencyPath(specdir() + Option::dir_sep + "tmake.conf") << " "; } const QStringList &included = project->values("QMAKE_INTERNAL_INCLUDED_FILES"); t << escapeDependencyPaths(included).join(" \\\n\t\t") << "\n\t" diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index d89c3b15bd..4c3be3daf1 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -247,7 +247,41 @@ public: virtual bool supportsMergedBuilds() { return false; } virtual bool mergeBuildProject(MakefileGenerator * /*other*/) { return false; } virtual bool openOutput(QFile &, const QString &build) const; - virtual bool isWindowsShell() const { return Option::target_mode == Option::TARG_WIN_MODE; } + virtual bool isWindowsShell() const { return Option::host_mode == Option::HOST_WIN_MODE; } + virtual bool isForSymbianSbsv2() const { return false; } // FIXME: killme - i'm ugly! + + /* The next one is to avoid having SymbianCommonGenerator as a virtually + inherited class of this class. Instead it is without a base class + (avoiding the virtual inheritance problem), and is allowed to use + functions defined in here. + + To illustrate: + +-------------------+ + | MakefileGenerator | + +-------------------+ + ^ ^ + | | + | X <-- Avoid this inheritance + | | + +------------------------+ +------------------------+ + | UnixMakefileGenerator | | SymbianCommonGenerator | + | or | | | + | NmakeMakefileGenerator | | | + +------------------------+ +------------------------+ + ^ ^ + | | + | | + | | + +-----------------------------+ + | SymbianMakefileTemplate<> | + +-----------------------------+ + + We want to avoid the famous diamond problem, because if we have that, we need + virtual inheritance, which not all compilers like. Therefore, we break the + link as illustrated. Instead, we have a pointer to MakefileGenerator inside + SymbianCommonGenerator, and allows full access by making it a friend here. + */ + friend class SymbianCommonGenerator; }; inline void MakefileGenerator::setNoIO(bool o) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 415119371a..e98831dd34 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -58,6 +58,8 @@ MetaMakefileGenerator::~MetaMakefileGenerator() delete project; } +#ifndef QT_QMAKE_PARSER_ONLY + class BuildsMetaMakefileGenerator : public MetaMakefileGenerator { private: @@ -293,7 +295,15 @@ SubdirsMetaMakefileGenerator::init() init_flag = true; bool hasError = false; - if(Option::recursive) { + // It might make sense to bequeath the CONFIG option to the recursed + // projects. OTOH, one would most likely have it in all projects anyway - + // either through a qmakespec, a .qmake.cache or explicitly - as otherwise + // running qmake in a subdirectory would have a different auto-recurse + // setting than in parent directories. + bool recurse = Option::recursive == Option::QMAKE_RECURSIVE_YES + || (Option::recursive == Option::QMAKE_RECURSIVE_DEFAULT + && project->isRecursive()); + if(recurse) { QString old_output_dir = Option::output_dir; QString old_output = Option::output.fileName(); QString oldpwd = qmake_getpwd(); @@ -375,7 +385,7 @@ SubdirsMetaMakefileGenerator::init() Subdir *self = new Subdir; self->input_dir = qmake_getpwd(); self->output_dir = Option::output_dir; - if(!Option::recursive || (!Option::output.fileName().endsWith(Option::dir_sep) && !QFileInfo(Option::output).isDir())) + if(!recurse || (!Option::output.fileName().endsWith(Option::dir_sep) && !QFileInfo(Option::output).isDir())) self->output_file = Option::output.fileName(); self->makefile = new BuildsMetaMakefileGenerator(project, name, false); self->makefile->init(); @@ -432,10 +442,11 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "pbuilder_pbx.h" #include "msvc_nmake.h" #include "borland_bmake.h" -#include "msvc_dsp.h" #include "msvc_vcproj.h" +#include "msvc_vcxproj.h" #include "symmake_abld.h" #include "symmake_sbsv2.h" +#include "symbian_makefile.h" QT_END_INCLUDE_NAMESPACE MakefileGenerator * @@ -458,24 +469,25 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO) mkfile = new MingwMakefileGenerator; } else if(gen == "PROJECTBUILDER" || gen == "XCODE") { mkfile = new ProjectBuilderMakefileGenerator; - } else if(gen == "MSVC") { - // Visual Studio =< v6.0 - if(proj->first("TEMPLATE").indexOf(QRegExp("^vc.*")) != -1) - mkfile = new DspMakefileGenerator; - else - mkfile = new NmakeMakefileGenerator; } else if(gen == "MSVC.NET") { - // Visual Studio >= v7.0 - if(proj->first("TEMPLATE").indexOf(QRegExp("^vc.*")) != -1 || proj->first("TEMPLATE").indexOf(QRegExp("^ce.*")) != -1) + if (proj->first("TEMPLATE").startsWith("vc")) mkfile = new VcprojGenerator; else mkfile = new NmakeMakefileGenerator; + } else if(gen == "MSBUILD") { + // Visual Studio >= v11.0 + if (proj->first("TEMPLATE").startsWith("vc")) + mkfile = new VcxprojGenerator; + else + mkfile = new NmakeMakefileGenerator; } else if(gen == "BMAKE") { mkfile = new BorlandMakefileGenerator; } else if(gen == "SYMBIAN_ABLD") { mkfile = new SymbianAbldMakefileGenerator; } else if(gen == "SYMBIAN_SBSV2") { mkfile = new SymbianSbsv2MakefileGenerator; + } else if(gen == "SYMBIAN_UNIX") { + mkfile = new SymbianMakefileTemplate<UnixMakefileGenerator>; } else { fprintf(stderr, "Unknown generator specified: %s\n", gen.toLatin1().constData()); } @@ -503,4 +515,49 @@ MetaMakefileGenerator::createMetaGenerator(QMakeProject *proj, const QString &na return ret; } +#endif // QT_QMAKE_PARSER_ONLY + +bool +MetaMakefileGenerator::modesForGenerator(const QString &gen, + Option::HOST_MODE *host_mode, Option::TARG_MODE *target_mode) +{ + if (gen == "UNIX") { +#ifdef Q_OS_MAC + *host_mode = Option::HOST_MACX_MODE; + *target_mode = Option::TARG_MACX_MODE; +#else + *host_mode = Option::HOST_UNIX_MODE; + *target_mode = Option::TARG_UNIX_MODE; +#endif + } else if (gen == "MSVC.NET" || gen == "BMAKE" || gen == "MSBUILD") { + *host_mode = Option::HOST_WIN_MODE; + *target_mode = Option::TARG_WIN_MODE; + } else if (gen == "MINGW") { +#if defined(Q_OS_MAC) + *host_mode = Option::HOST_MACX_MODE; +#elif defined(Q_OS_UNIX) + *host_mode = Option::HOST_UNIX_MODE; +#else + *host_mode = Option::HOST_WIN_MODE; +#endif + *target_mode = Option::TARG_WIN_MODE; + } else if (gen == "PROJECTBUILDER" || gen == "XCODE") { + *host_mode = Option::HOST_MACX_MODE; + *target_mode = Option::TARG_MACX_MODE; + } else if (gen == "SYMBIAN_ABLD" || gen == "SYMBIAN_SBSV2" || gen == "SYMBIAN_UNIX") { +#if defined(Q_OS_MAC) + *host_mode = Option::HOST_MACX_MODE; +#elif defined(Q_OS_UNIX) + *host_mode = Option::HOST_UNIX_MODE; +#else + *host_mode = Option::HOST_WIN_MODE; +#endif + *target_mode = Option::TARG_SYMBIAN_MODE; + } else { + fprintf(stderr, "Unknown generator specified: %s\n", gen.toLatin1().constData()); + return false; + } + return true; +} + QT_END_NAMESPACE diff --git a/qmake/generators/metamakefile.h b/qmake/generators/metamakefile.h index 867511589b..e559c8e863 100644 --- a/qmake/generators/metamakefile.h +++ b/qmake/generators/metamakefile.h @@ -42,6 +42,8 @@ #ifndef METAMAKEFILE_H #define METAMAKEFILE_H +#include <option.h> + #include <qlist.h> #include <qstring.h> @@ -65,6 +67,9 @@ public: static MetaMakefileGenerator *createMetaGenerator(QMakeProject *proj, const QString &name, bool op=true, bool *success = 0); static MakefileGenerator *createMakefileGenerator(QMakeProject *proj, bool noIO = false); + static bool modesForGenerator(const QString &generator, + Option::HOST_MODE *host_mode, Option::TARG_MODE *target_mode); + inline QMakeProject *projectFile() const { return project; } virtual bool init() = 0; diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 8622cd9fd4..d2256359db 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -111,7 +111,7 @@ ProjectGenerator::init() add_depend = true; if(dir.right(1) != Option::dir_sep) dir += Option::dir_sep; - if(Option::recursive) { + if(Option::recursive == Option::QMAKE_RECURSIVE_YES) { QStringList files = QDir(dir).entryList(QDir::Files); for(int i = 0; i < (int)files.count(); i++) { if(files[i] != "." && files[i] != "..") @@ -138,7 +138,7 @@ ProjectGenerator::init() dir = regex.left(s+1); regex = regex.right(regex.length() - (s+1)); } - if(Option::recursive) { + if(Option::recursive == Option::QMAKE_RECURSIVE_YES) { QStringList entries = QDir(dir).entryList(QDir::Dirs); for(int i = 0; i < (int)entries.count(); i++) { if(entries[i] != "." && entries[i] != "..") { @@ -193,7 +193,7 @@ ProjectGenerator::init() subdirs.append(nd); } } - if(Option::recursive) { + if(Option::recursive == Option::QMAKE_RECURSIVE_YES) { QStringList dirs = QDir(newdir).entryList(QDir::Dirs); for(int i = 0; i < (int)dirs.count(); i++) { QString nd = fileFixify(newdir + QDir::separator() + dirs[i]); @@ -230,7 +230,8 @@ ProjectGenerator::init() } } } - if(Option::recursive && !knownDirs.contains(newdir, Qt::CaseInsensitive)) + if(Option::recursive == Option::QMAKE_RECURSIVE_YES + && !knownDirs.contains(newdir, Qt::CaseInsensitive)) knownDirs.append(newdir); } } diff --git a/qmake/generators/symbian/initprojectdeploy_symbian.cpp b/qmake/generators/symbian/initprojectdeploy_symbian.cpp index 81c940840b..776a6460d1 100644 --- a/qmake/generators/symbian/initprojectdeploy_symbian.cpp +++ b/qmake/generators/symbian/initprojectdeploy_symbian.cpp @@ -50,6 +50,7 @@ #include <symbian/epocroot.h> #define SYSBIN_DIR "/sys/bin" +#define HW_Z_DIR "epoc32/data/z" #define SUFFIX_DLL "dll" #define SUFFIX_EXE "exe" @@ -65,10 +66,11 @@ static bool isPlugin(const QFileInfo& info, const QString& devicePath) { // Libraries are plugins if deployment path is something else than // SYSBIN_DIR with or without drive letter - if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive) && - (devicePath.size() < 8 || - (0 != devicePath.compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive) && - 0 != devicePath.mid(1).compare(QLatin1String(":" SYSBIN_DIR), Qt::CaseInsensitive)))) { + if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive) + && (devicePath.size() < 8 + || (0 != devicePath.compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive) + && 0 != devicePath.mid(1).compare(QLatin1String(":" SYSBIN_DIR), Qt::CaseInsensitive) + && 0 != devicePath.compare(epocRoot() + QLatin1String(HW_Z_DIR SYSBIN_DIR))))) { return true; } else { return false; @@ -91,12 +93,13 @@ static void createPluginStub(const QFileInfo& info, QStringList& generatedDirs, QStringList& generatedFiles) { - QDir().mkpath(QLatin1String(PLUGIN_STUB_DIR)); - if (!generatedDirs.contains(PLUGIN_STUB_DIR)) - generatedDirs << PLUGIN_STUB_DIR; + QString pluginStubDir = Option::output_dir + QLatin1Char('/') + QLatin1String(PLUGIN_STUB_DIR); + QDir().mkpath(pluginStubDir); + if (!generatedDirs.contains(pluginStubDir)) + generatedDirs << pluginStubDir; // Plugin stubs must have different name from the actual plugins, because // the toolchain for creating ROM images cannot handle non-binary .dll files properly. - QFile stubFile(QLatin1String(PLUGIN_STUB_DIR "/") + info.completeBaseName() + "." SUFFIX_QTPLUGIN); + QFile stubFile(pluginStubDir + QLatin1Char('/') + info.completeBaseName() + QLatin1Char('.') + QLatin1String(SUFFIX_QTPLUGIN)); if (stubFile.open(QIODevice::WriteOnly)) { if (!generatedFiles.contains(stubFile.fileName())) generatedFiles << stubFile.fileName(); @@ -155,6 +158,7 @@ void initProjectDeploySymbian(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath, bool deployBinaries, + bool epocBuild, const QString &platform, const QString &build, QStringList& generatedDirs, @@ -170,7 +174,13 @@ void initProjectDeploySymbian(QMakeProject* project, if (targetPath.size() > 1) { targetPathHasDriveLetter = targetPath.at(1) == QLatin1Char(':'); } - QString deploymentDrive = targetPathHasDriveLetter ? targetPath.left(2) : QLatin1String("c:"); + + QString deploymentDrive; + if (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { + deploymentDrive = epocRoot() + HW_Z_DIR; + } else { + deploymentDrive = targetPathHasDriveLetter ? targetPath.left(2) : QLatin1String("c:"); + } foreach(QString item, project->values("DEPLOYMENT")) { QString devicePath = project->first(item + ".path"); @@ -188,6 +198,7 @@ void initProjectDeploySymbian(QMakeProject* project, devicePathWithoutDrive.remove(0,2); } if (!deployBinaries + && 0 != platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM)) && !devicePathWithoutDrive.isEmpty() && (0 == devicePathWithoutDrive.compare(project->values("APP_RESOURCE_DIR").join(""), Qt::CaseInsensitive) || 0 == devicePathWithoutDrive.compare(project->values("REG_RESOURCE_IMPORT_DIR").join(""), Qt::CaseInsensitive))) { @@ -207,35 +218,29 @@ void initProjectDeploySymbian(QMakeProject* project, // Create output path devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('/') + devicePath)); } else { - if (!platform.compare(QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM))) { + if (0 == platform.compare(QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM))) { if (devicePathHasDriveLetter) { devicePath = epocRoot() + "epoc32/winscw/" + devicePath.remove(1, 1); } else { devicePath = epocRoot() + "epoc32/winscw/c" + devicePath; } } else { - if (!devicePathHasDriveLetter) { - if (!platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { - //For plugin deployment under ARM no needed drive letter - devicePath = epocRoot() + "epoc32/data/z" + devicePath; - } else if (targetPathHasDriveLetter) { - // Drive letter needed if targetpath contains one and it is not already in - devicePath = deploymentDrive + devicePath; - } - } else { - //it is necessary to delete drive letter for ARM deployment - if (!platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { - devicePath.remove(0,2); - devicePath = epocRoot() + "epoc32/data/z" + devicePath; - } + if (devicePathHasDriveLetter + && 0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { + devicePath.remove(0,2); + } + if (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM)) + || (!devicePathHasDriveLetter && targetPathHasDriveLetter)) { + devicePath = deploymentDrive + devicePath; } } } devicePath.replace(QLatin1String("\\"), QLatin1String("/")); - if (!deployBinaries && - 0 == devicePath.right(8).compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive)) { + if (!deployBinaries + && 0 == devicePath.right(8).compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive) + && 0 != platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { // Skip deploying to SYSBIN_DIR for anything but binary deployments // Note: Deploying pre-built binaries also follow this rule, so emulator builds // will not get those deployed. Since there is no way to differentiate currently @@ -264,7 +269,11 @@ void initProjectDeploySymbian(QMakeProject* project, if (isBinary(info)) { if (deployBinaries) { // Executables and libraries are deployed to \sys\bin - QFileInfo targetPath(epocRoot() + "epoc32/release/" + platform + "/" + build + "/"); + QFileInfo targetPath; + if (epocBuild) + targetPath.setFile(epocRoot() + "epoc32/release/" + platform + "/" + build + "/"); + else + targetPath.setFile(info.path() + QDir::separator()); if(devicePathHasDriveLetter) { deploymentList.append(CopyItem( Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(), @@ -275,7 +284,7 @@ void initProjectDeploySymbian(QMakeProject* project, deploymentList.append(CopyItem( Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(), false, true), - fixPathToEpocOS(deploymentDrive + QLatin1String(SYSBIN_DIR "/") + fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/") + info.fileName()))); } } @@ -308,7 +317,8 @@ void initProjectDeploySymbian(QMakeProject* project, if (isPlugin(iterator.fileInfo(), devicePath)) { // This deploys pre-built plugins. Other pre-built binaries will deploy normally, // as they have SYSBIN_DIR target path. - if (deployBinaries) { + if (deployBinaries + || (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM)))) { if (devicePathHasDriveLetter) { deploymentList.append(CopyItem( Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()), @@ -317,7 +327,7 @@ void initProjectDeploySymbian(QMakeProject* project, } else { deploymentList.append(CopyItem( Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()), - fixPathToEpocOS(deploymentDrive + QLatin1String(SYSBIN_DIR "/") + fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/") + iterator.fileName()))); } } @@ -334,4 +344,21 @@ void initProjectDeploySymbian(QMakeProject* project, } } } + + // Remove deployments that do not actually do anything + if (0 == platform.compare(QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM)) + || 0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) { + QMutableListIterator<CopyItem> i(deploymentList); + while(i.hasNext()) { + CopyItem &item = i.next(); + QFileInfo fromItem(item.from); + QFileInfo toItem(item.to); +#if defined(Q_OS_WIN) + if (0 == fromItem.absoluteFilePath().compare(toItem.absoluteFilePath(), Qt::CaseInsensitive)) +#else + if (0 == fromItem.absoluteFilePath().compare(toItem.absoluteFilePath())) +#endif + i.remove(); + } + } } diff --git a/qmake/generators/symbian/initprojectdeploy_symbian.h b/qmake/generators/symbian/initprojectdeploy_symbian.h index c621915c7c..2653d2a46f 100644 --- a/qmake/generators/symbian/initprojectdeploy_symbian.h +++ b/qmake/generators/symbian/initprojectdeploy_symbian.h @@ -69,6 +69,7 @@ extern void initProjectDeploySymbian(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath, bool deployBinaries, + bool epocBuild, const QString &platform, const QString &build, QStringList& generatedDirs, diff --git a/qmake/generators/symbian/symbian_makefile.h b/qmake/generators/symbian/symbian_makefile.h new file mode 100644 index 0000000000..94f01453c7 --- /dev/null +++ b/qmake/generators/symbian/symbian_makefile.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SYMBIAN_MAKEFILE_H +#define SYMBIAN_MAKEFILE_H + +#include "symbiancommon.h" + +// This allows us to reuse the code for both win32 and unix makefile generators. +template <class T> +class SymbianMakefileTemplate : public T, public SymbianCommonGenerator +{ +public: + SymbianMakefileTemplate() : SymbianCommonGenerator(this) {} + + void init() + { + T::init(); + SymbianCommonGenerator::init(); + } + + bool writeMakefile(QTextStream &t) + { + QString numberOfIcons; + QString iconFile; + QMap<QString, QStringList> userRssRules; + readRssRules(numberOfIcons, iconFile, userRssRules); + + // Generate pkg files if there are any actual files to deploy + bool generatePkg = false; + + if (targetType == TypeExe) { + generatePkg = true; + } else { + const QStringList deployments = this->project->values("DEPLOYMENT"); + for (int i = 0; i < deployments.count(); ++i) { + if (!this->project->values(deployments.at(i) + ".sources").isEmpty()) { + generatePkg = true; + break; + } + } + } + + if (generatePkg) { + generatePkgFile(iconFile, false); + } + + // Get the application translations and convert to symbian OS lang code, i.e. decical number + QStringList symbianLangCodes = symbianLangCodesFromTsFiles(); + + if (targetType == TypeExe) { + if (!this->project->values("CONFIG").contains("no_icon", Qt::CaseInsensitive)) { + writeRegRssFile(userRssRules); + writeRssFile(numberOfIcons, iconFile); + writeLocFile(symbianLangCodes); + } + } + + writeCustomDefFile(); + + return T::writeMakefile(t); + } +}; + +#endif // SYMBIAN_MAKEFILE_H diff --git a/qmake/generators/symbian/symbiancommon.cpp b/qmake/generators/symbian/symbiancommon.cpp new file mode 100644 index 0000000000..a60ae076b9 --- /dev/null +++ b/qmake/generators/symbian/symbiancommon.cpp @@ -0,0 +1,1032 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "symbiancommon.h" +#include <qdebug.h> + +// Included from tools/shared +#include <symbian/epocroot.h> + +#define RESOURCE_DIRECTORY_RESOURCE "\\\\resource\\\\apps\\\\" + +#define RSS_RULES "RSS_RULES" +#define RSS_RULES_BASE "RSS_RULES." +#define RSS_TAG_NBROFICONS "number_of_icons" +#define RSS_TAG_ICONFILE "icon_file" +#define RSS_TAG_HEADER "header" +#define RSS_TAG_SERVICE_LIST "service_list" +#define RSS_TAG_FILE_OWNERSHIP_LIST "file_ownership_list" +#define RSS_TAG_DATATYPE_LIST "datatype_list" +#define RSS_TAG_FOOTER "footer" +#define RSS_TAG_DEFAULT "default_rules" // Same as just giving rules without tag + +#define PLUGIN_COMMON_DEF_FILE_ACTUAL "plugin_commonu.def" + +#define MANUFACTURER_NOTE_FILE "manufacturer_note.txt" +#define DEFAULT_MANUFACTURER_NOTE \ + "The package is not supported for devices from this manufacturer. Please try the selfsigned " \ + "version of the package instead." + +SymbianCommonGenerator::SymbianCommonGenerator(MakefileGenerator *generator) + : generator(generator) +{ +} + +void SymbianCommonGenerator::init() +{ + QMakeProject *project = generator->project; + fixedTarget = project->first("QMAKE_ORIG_TARGET"); + if (fixedTarget.isEmpty()) + fixedTarget = project->first("TARGET"); + fixedTarget = generator->unescapeFilePath(fixedTarget); + fixedTarget = removePathSeparators(fixedTarget); + if (project->first("MAKEFILE_GENERATOR") == "SYMBIAN_ABLD" + || project->first("MAKEFILE_GENERATOR") == "SYMBIAN_SBSV2") + removeEpocSpecialCharacters(fixedTarget); + else + removeSpecialCharacters(fixedTarget); + + // This should not be empty since the mkspecs are supposed to set it if missing. + uid3 = project->first("TARGET.UID3").trimmed(); + + if ((project->values("TEMPLATE")).contains("app")) + targetType = TypeExe; + else if ((project->values("TEMPLATE")).contains("lib")) { + // Check CONFIG to see if we are to build staticlib or dll + if (project->isActiveConfig("staticlib") || project->isActiveConfig("static")) + targetType = TypeLib; + else if (project->isActiveConfig("plugin")) + targetType = TypePlugin; + else + targetType = TypeDll; + } else { + targetType = TypeSubdirs; + } + + // UID is valid as either hex or decimal, so just convert it to number and back to hex + // to get proper string for private dir + bool conversionOk = false; + uint uidNum = uid3.toUInt(&conversionOk, 0); + + if (!conversionOk) { + fprintf(stderr, "Error: Invalid UID \"%s\".\n", uid3.toUtf8().constData()); + } else { + privateDirUid.setNum(uidNum, 16); + while (privateDirUid.length() < 8) + privateDirUid.insert(0, QLatin1Char('0')); + } +} + +bool SymbianCommonGenerator::containsStartWithItem(const QChar &c, const QStringList& src) +{ + bool result = false; + foreach(QString str, src) { + if (str.startsWith(c)) { + result = true; + break; + } + } + return result; +} + +void SymbianCommonGenerator::removeSpecialCharacters(QString& str) +{ + // When modifying this method check also symbianRemoveSpecialCharacters in symbian.conf + str.replace(QString("/"), QString("_")); + str.replace(QString("\\"), QString("_")); + str.replace(QString(" "), QString("_")); +} + +void SymbianCommonGenerator::removeEpocSpecialCharacters(QString& str) +{ + // When modifying this method check also symbianRemoveSpecialCharacters in symbian.conf + str.replace(QString("-"), QString("_")); + str.replace(QString(":"), QString("_")); + str.replace(QString("."), QString("_")); + removeSpecialCharacters(str); +} + +QString romPath(const QString& path) +{ + if(path.length() > 2 && path[1] == ':') + return QLatin1String("z:") + path.mid(2); + return QLatin1String("z:") + path; +} + +void SymbianCommonGenerator::generatePkgFile(const QString &iconFile, bool epocBuild) +{ + QMakeProject *project = generator->project; + QString pkgFilename = Option::output_dir + QLatin1Char('/') + + QString("%1_template.pkg").arg(fixedTarget); + + QFile pkgFile(pkgFilename); + if (!pkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + PRINT_FILE_CREATE_ERROR(pkgFilename); + return; + } + + QString stubPkgFileName = Option::output_dir + QLatin1Char('/') + + QString("%1_stub.pkg").arg(fixedTarget); + + QFile stubPkgFile(stubPkgFileName); + if (!stubPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + PRINT_FILE_CREATE_ERROR(stubPkgFileName); + return; + } + + generatedFiles << pkgFile.fileName(); + QTextStream t(&pkgFile); + generatedFiles << stubPkgFile.fileName(); + QTextStream ts(&stubPkgFile); + + QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n"); + if (installerSisHeader.isEmpty()) + installerSisHeader = "0xA000D7CE"; // Use default self-signable UID if not defined + + QString wrapperStreamBuffer; + QTextStream tw(&wrapperStreamBuffer); + + QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate); + + // Header info + QString wrapperPkgFilename = Option::output_dir + QLatin1Char('/') + QString("%1_installer.%2") + .arg(fixedTarget).arg("pkg"); + + QString headerComment = "; %1 generated by qmake at %2\n" + "; This file is generated by qmake and should not be modified by the user\n" + ";\n\n"; + t << headerComment.arg(pkgFilename).arg(dateStr); + tw << headerComment.arg(wrapperPkgFilename).arg(dateStr); + ts << headerComment.arg(stubPkgFileName).arg(dateStr); + + // Construct QStringList from pkg_prerules since we need search it before printed to file + // Note: Though there can't be more than one language or header line, use stringlists + // in case user wants comments to go with the rules. + QStringList rawPkgPreRules; + QStringList languageRules; + QStringList headerRules; + foreach(QString deploymentItem, project->values("DEPLOYMENT")) { + foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line mmp statements + if (pkgrulesValue.isEmpty()) { + if (pkgrulesItem.startsWith("&")) + languageRules << pkgrulesItem; + else if (pkgrulesItem.startsWith("#")) + headerRules << pkgrulesItem; + else + rawPkgPreRules << pkgrulesItem; + } else { + if (containsStartWithItem('&', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + languageRules << pkgrule; + } + } else if (containsStartWithItem('#', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + headerRules << pkgrule; + } + } else { + foreach(QString pkgrule, pkgrulesValue) { + rawPkgPreRules << pkgrule; + } + } + } + } + } + + // Apply some defaults if specific data does not exist in PKG pre-rules + + if (languageRules.isEmpty()) { + // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS) + languageRules << "; Language\n&EN\n\n"; + } else if (headerRules.isEmpty()) { + // In case user defines langs, he must take care also about SIS header + fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n"); + } + + t << languageRules.join("\n") << endl; + tw << languageRules.join("\n") << endl; + ts << languageRules.join("\n") << endl; + + // Determine application version. If version has missing component values, + // those will default to zero. + // If VERSION is missing altogether or is invalid, use "1,0,0" + QStringList verNumList = project->first("VERSION").split('.'); + uint major = 0; + uint minor = 0; + uint patch = 0; + bool success = false; + + if (verNumList.size() > 0) { + major = verNumList[0].toUInt(&success); + if (success && verNumList.size() > 1) { + minor = verNumList[1].toUInt(&success); + if (success && verNumList.size() > 2) { + patch = verNumList[2].toUInt(&success); + } + } + } + + QString applicationVersion("1,0,0"); + if (success) + applicationVersion = QString("%1,%2,%3").arg(major).arg(minor).arg(patch); + + // Append package build version number if it is set + QString pkgBuildVersion = project->first("DEPLOYMENT.pkg_build_version"); + if (!pkgBuildVersion.isEmpty()) { + success = false; + uint build = pkgBuildVersion.toUInt(&success); + if (success && build < 100) { + if (pkgBuildVersion.size() == 1) + pkgBuildVersion.prepend(QLatin1Char('0')); + applicationVersion.append(pkgBuildVersion); + } else { + fprintf(stderr, "Warning: Invalid DEPLOYMENT.pkg_build_version (%s), must be a number between 0 - 99\n", qPrintable(pkgBuildVersion)); + } + } + + // Package header + QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n"; + QString visualTarget = generator->escapeFilePath(project->first("TARGET")); + + visualTarget = removePathSeparators(visualTarget); + QString wrapperTarget = visualTarget + " installer"; + + if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) { + tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion); + } else { + tw << installerSisHeader << endl; + } + + if (headerRules.isEmpty()) { + t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion); + ts << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion); + } + else { + t << headerRules.join("\n") << endl; + ts << headerRules.join("\n") << endl; + } + + // Localized vendor name + QString vendorName; + if (!containsStartWithItem('%', rawPkgPreRules)) { + vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n"; + } + + // Unique vendor name + if (!containsStartWithItem(':', rawPkgPreRules)) { + vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n"; + } + + t << vendorName; + tw << vendorName; + ts << vendorName; + + // PKG pre-rules - these are added before actual file installations i.e. SIS package body + if (rawPkgPreRules.size()) { + QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + t << comment; + tw << comment; + ts << comment; + + foreach(QString item, rawPkgPreRules) { + // Only regular pkg file should have package dependencies + if (item.startsWith("(")) { + t << item << endl; + } + // stub pkg file should not have platform dependencies + else if (item.startsWith("[")) { + t << item << endl; + tw << item << endl; + } + else { + t << item << endl; + ts << item << endl; + tw << item << endl; + } + } + t << endl; + ts << endl; + tw << endl; + } + + // Begin Manufacturer block + if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { + QString manufacturerStr("IF "); + foreach(QString manufacturer, project->values("DEPLOYMENT.manufacturers")) { + manufacturerStr.append(QString("(MANUFACTURER)=(%1) OR \n ").arg(manufacturer)); + } + // Remove the final OR + manufacturerStr.chop(8); + t << manufacturerStr << endl; + } + + // Install paths on the phone *** should be dynamic at some point + QString installPathBin = "!:\\sys\\bin"; + QString installPathResource = "!:\\resource\\apps"; + QString installPathRegResource = "!:\\private\\10003a3f\\import\\apps"; + + // Find location of builds + QString destDirBin; + QString destDirResource; + QString destDirRegResource; + if (epocBuild) { + destDirBin = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)").arg(epocRoot()); + destDirResource = QString("%1epoc32/data/z/resource/apps").arg(epocRoot()); + destDirRegResource = QString("%1epoc32/data/z/private/10003a3f/import/apps").arg(epocRoot()); + } else { + destDirBin = project->first("DESTDIR"); + if (destDirBin.isEmpty()) + destDirBin = "."; + else if (destDirBin.endsWith('/') || destDirBin.endsWith('\\')) + destDirBin.chop(1); + destDirResource = destDirBin; + destDirRegResource = destDirBin; + } + + if (targetType == TypeExe) { + // deploy .exe file + t << "; Executable and default resource files" << endl; + QString exeFile = fixedTarget + ".exe"; + t << QString("\"%1/%2\" - \"%3\\%4\"") + .arg(destDirBin) + .arg(exeFile) + .arg(installPathBin) + .arg(exeFile) << endl; + ts << QString("\"\" - \"%1\\%2\"") + .arg(romPath(installPathBin)) + .arg(exeFile) << endl; + + // deploy rsc & reg_rsc file + if (!project->isActiveConfig("no_icon")) { + t << QString("\"%1/%2\" - \"%3\\%4\"") + .arg(destDirResource) + .arg(fixedTarget + ".rsc") + .arg(installPathResource) + .arg(fixedTarget + ".rsc") << endl; + ts << QString("\"\" - \"%1\\%2\"") + .arg(romPath(installPathResource)) + .arg(fixedTarget + ".rsc") << endl; + + t << QString("\"%1/%2\" - \"%3\\%4\"") + .arg(destDirRegResource) + .arg(fixedTarget + "_reg.rsc") + .arg(installPathRegResource) + .arg(fixedTarget + "_reg.rsc") << endl; + ts << QString("\"\" - \"%1\\%2\"") + .arg(romPath(installPathRegResource)) + .arg(fixedTarget + "_reg.rsc") << endl; + + if (!iconFile.isEmpty()) { + if (epocBuild) { + t << QString("\"%1epoc32/data/z%2\" - \"!:%3\"") + .arg(epocRoot()) + .arg(iconFile) + .arg(QDir::toNativeSeparators(iconFile)) << endl << endl; + ts << QString("\"\" - \"%1\"") + .arg(romPath(QDir::toNativeSeparators(iconFile))) << endl << endl; + } else { + QDir mifIconDir(project->first("DESTDIR")); + QFileInfo mifIcon(mifIconDir.relativeFilePath(project->first("TARGET"))); + QString mifIconFileName = mifIcon.fileName(); + mifIconFileName.append(".mif"); + t << QString("\"%1/%2\" - \"!:%3\"") + .arg(mifIcon.path()) + .arg(mifIconFileName) + .arg(QDir::toNativeSeparators(iconFile)) << endl << endl; + ts << QString("\"\" - \"%1\"") + .arg(romPath(QDir::toNativeSeparators(iconFile))) << endl << endl; + } + } + } + } + + // deploy any additional DEPLOYMENT files + QString remoteTestPath; + QString zDir; + remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid); + if (epocBuild) + zDir = epocRoot() + QLatin1String("epoc32/data/z"); + + DeploymentList depList; + initProjectDeploySymbian(project, depList, remoteTestPath, true, epocBuild, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles); + if (depList.size()) + t << "; DEPLOYMENT" << endl; + for (int i = 0; i < depList.size(); ++i) { + QString from = depList.at(i).from; + QString to = depList.at(i).to; + + if (epocBuild) { + // Deploy anything not already deployed from under epoc32 instead from under + // \epoc32\data\z\ to enable using pkg file without rebuilding + // the project, which can be useful for some binary only distributions. + if (!from.contains(QLatin1String("epoc32"), Qt::CaseInsensitive)) { + from = to; + if (from.size() > 1 && from.at(1) == QLatin1Char(':')) + from = from.mid(2); + from.prepend(zDir); + } + } + + t << QString("\"%1\" - \"%2\"").arg(from.replace('\\','/')).arg(to) << endl; + ts << QString("\"\" - \"%1\"").arg(romPath(to)) << endl; + } + t << endl; + ts << endl; + + // PKG post-rules - these are added after actual file installations i.e. SIS package body + t << "; Manual PKG post-rules from PRO files" << endl; + foreach(QString deploymentItem, project->values("DEPLOYMENT")) { + foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_postrules")) { + QStringList pkgrulesValue = project->values(pkgrulesItem); + // If there is no stringlist defined for a rule, use rule name directly + // This is convenience for defining single line statements + if (pkgrulesValue.isEmpty()) { + t << pkgrulesItem << endl; + } else { + foreach(QString pkgrule, pkgrulesValue) { + t << pkgrule << endl; + } + } + t << endl; + } + } + + // Close Manufacturer block + if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { + QString manufacturerFailNoteFile; + if (project->values("DEPLOYMENT.manufacturers.fail_note").isEmpty()) { + manufacturerFailNoteFile = QString("%1_" MANUFACTURER_NOTE_FILE).arg(uid3); + QFile ft(manufacturerFailNoteFile); + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t2(&ft); + + t2 << QString(DEFAULT_MANUFACTURER_NOTE) << endl; + } else { + PRINT_FILE_CREATE_ERROR(manufacturerFailNoteFile) + } + } else { + manufacturerFailNoteFile = project->values("DEPLOYMENT.manufacturers.fail_note").join(""); + } + + t << "ELSEIF NOT(0) ; MANUFACTURER" << endl + << "\"" << generator->fileInfo(manufacturerFailNoteFile).absoluteFilePath() << "\"" + << " - \"\", FILETEXT, TEXTEXIT" << endl + << "ENDIF ; MANUFACTURER" << endl; + } + + // Write wrapper pkg + if (!installerSisHeader.isEmpty()) { + QFile wrapperPkgFile(wrapperPkgFilename); + if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + PRINT_FILE_CREATE_ERROR(wrapperPkgFilename); + return; + } + + generatedFiles << wrapperPkgFile.fileName(); + QTextStream twf(&wrapperPkgFile); + + twf << wrapperStreamBuffer << endl; + + // Wrapped files deployment + QString currentPath = qmake_getpwd(); + QString sisName = QString("%1.sis").arg(fixedTarget); + twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\private\\2002CCCE\\import\\" << sisName << "\"" << endl; + + QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath); + bootStrapPath.append("/smartinstaller.sis"); + QFileInfo fi(generator->fileInfo(bootStrapPath)); + twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl; + } +} + +QString SymbianCommonGenerator::removePathSeparators(QString &file) +{ + QString ret = file; + + if (QDir::separator().unicode() != '/') + ret.replace(QDir::separator(), QLatin1Char('/')); + + if (ret.indexOf(QLatin1Char('/')) >= 0) + ret.remove(0, ret.lastIndexOf(QLatin1Char('/')) + 1); + + return ret; +} + +void SymbianCommonGenerator::writeRegRssFile(QMap<QString, QStringList> &userItems) +{ + QString filename(fixedTarget); + filename.append("_reg.rss"); + if (!Option::output_dir.isEmpty()) + filename = Option::output_dir + '/' + filename; + QFile ft(filename); + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t(&ft); + t << "// ============================================================================" << endl; + t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; + t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; + t << "// * This file is generated by qmake and should not be modified by the" << endl; + t << "// * user." << endl; + t << "// ============================================================================" << endl; + t << endl; + t << "#include <" << fixedTarget << ".rsg>" << endl; + t << "#include <appinfo.rh>" << endl; + foreach(QString item, userItems[RSS_TAG_HEADER]) + t << item << endl; + t << endl; + t << "UID2 KUidAppRegistrationResourceFile" << endl; + t << "UID3 " << uid3 << endl << endl; + t << "RESOURCE APP_REGISTRATION_INFO" << endl; + t << "\t{" << endl; + t << "\tapp_file=\"" << fixedTarget << "\";" << endl; + t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl; + + writeRegRssList(t, userItems[RSS_TAG_SERVICE_LIST], + QLatin1String(RSS_TAG_SERVICE_LIST), + QLatin1String("SERVICE_INFO")); + writeRegRssList(t, userItems[RSS_TAG_FILE_OWNERSHIP_LIST], + QLatin1String(RSS_TAG_FILE_OWNERSHIP_LIST), + QLatin1String("FILE_OWNERSHIP_INFO")); + writeRegRssList(t, userItems[RSS_TAG_DATATYPE_LIST], + QLatin1String(RSS_TAG_DATATYPE_LIST), + QLatin1String("DATATYPE")); + t << endl; + + foreach(QString item, userItems[RSS_TAG_DEFAULT]) + t << "\t" << item.replace("\n","\n\t") << endl; + t << "\t}" << endl; + + foreach(QString item, userItems[RSS_TAG_FOOTER]) + t << item << endl; + } else { + PRINT_FILE_CREATE_ERROR(filename) + } +} + +void SymbianCommonGenerator::writeRegRssList(QTextStream &t, + QStringList &userList, + const QString &listTag, + const QString &listItem) +{ + int itemCount = userList.count(); + if (itemCount) { + t << "\t" << listTag << " ="<< endl; + t << "\t\t{" << endl; + foreach(QString item, userList) { + t << "\t\t" << listItem << endl; + t << "\t\t\t{" << endl; + t << "\t\t\t" << item.replace("\n","\n\t\t\t") << endl; + t << "\t\t\t}"; + if (--itemCount) + t << ","; + t << endl; + } + t << "\t\t}; "<< endl; + } +} + +void SymbianCommonGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile) +{ + QString filename(fixedTarget); + if (!Option::output_dir.isEmpty()) + filename = Option::output_dir + '/' + filename; + filename.append(".rss"); + QFile ft(filename); + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t(&ft); + t << "// ============================================================================" << endl; + t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; + t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; + t << "// * This file is generated by qmake and should not be modified by the" << endl; + t << "// * user." << endl; + t << "// ============================================================================" << endl; + t << endl; + t << "#include <appinfo.rh>" << endl; + t << "#include \"" << fixedTarget << ".loc\"" << endl; + t << endl; + t << "RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info" << endl; + t << "\t{" << endl; + t << "\tshort_caption = STRING_r_short_caption;" << endl; + t << "\tcaption_and_icon =" << endl; + t << "\tCAPTION_AND_ICON_INFO" << endl; + t << "\t\t{" << endl; + t << "\t\tcaption = STRING_r_caption;" << endl; + + QString rssIconFile = iconFile; + rssIconFile = rssIconFile.replace("/", "\\\\"); + + if (numberOfIcons.isEmpty() || rssIconFile.isEmpty()) { + // There can be maximum one item in this tag, validated when parsed + t << "\t\tnumber_of_icons = 0;" << endl; + t << "\t\ticon_file = \"\";" << endl; + } else { + // There can be maximum one item in this tag, validated when parsed + t << "\t\tnumber_of_icons = " << numberOfIcons << ";" << endl; + t << "\t\ticon_file = \"" << rssIconFile << "\";" << endl; + } + t << "\t\t};" << endl; + t << "\t}" << endl; + t << endl; + } else { + PRINT_FILE_CREATE_ERROR(filename); + } +} + +void SymbianCommonGenerator::writeLocFile(QStringList &symbianLangCodes) +{ + QString filename(fixedTarget); + if (!Option::output_dir.isEmpty()) + filename = Option::output_dir + '/' + filename; + filename.append(".loc"); + QFile ft(filename); + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t(&ft); + t << "// ============================================================================" << endl; + t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; + t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; + t << "// * This file is generated by qmake and should not be modified by the" << endl; + t << "// * user." << endl; + t << "// ============================================================================" << endl; + t << endl; + t << "#ifdef LANGUAGE_SC" << endl; + t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + foreach(QString lang, symbianLangCodes) { + t << "#elif defined LANGUAGE_" << lang << endl; + t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + } + t << "#else" << endl; + t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + t << "#endif" << endl; + } else { + PRINT_FILE_CREATE_ERROR(filename); + } +} + +void SymbianCommonGenerator::readRssRules(QString &numberOfIcons, + QString &iconFile, QMap<QString, + QStringList> &userRssRules) +{ + QMakeProject *project = generator->project; + for (QMap<QString, QStringList>::iterator it = project->variables().begin(); it != project->variables().end(); ++it) { + if (it.key().startsWith(RSS_RULES_BASE)) { + QString newKey = it.key().mid(sizeof(RSS_RULES_BASE) - 1); + if (newKey.isEmpty()) { + fprintf(stderr, "Warning: Empty RSS_RULES_BASE key encountered\n"); + continue; + } + QStringList newValues; + QStringList values = it.value(); + foreach(QString item, values) { + // If there is no stringlist defined for a rule, use rule value directly + // This is convenience for defining single line statements + if (project->values(item).isEmpty()) { + newValues << item; + } else { + QStringList itemList; + foreach(QString itemRow, project->values(item)) { + itemList << itemRow; + } + newValues << itemList.join("\n"); + } + } + // Verify thet there is exactly one value in RSS_TAG_NBROFICONS + if (newKey == RSS_TAG_NBROFICONS) { + if (newValues.count() == 1) { + numberOfIcons = newValues[0]; + } else { + fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n", + RSS_RULES_BASE, RSS_TAG_NBROFICONS); + continue; + } + // Verify thet there is exactly one value in RSS_TAG_ICONFILE + } else if (newKey == RSS_TAG_ICONFILE) { + if (newValues.count() == 1) { + iconFile = newValues[0]; + } else { + fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n", + RSS_RULES_BASE, RSS_TAG_ICONFILE); + continue; + } + } else if (newKey == RSS_TAG_HEADER + || newKey == RSS_TAG_SERVICE_LIST + || newKey == RSS_TAG_FILE_OWNERSHIP_LIST + || newKey == RSS_TAG_DATATYPE_LIST + || newKey == RSS_TAG_FOOTER + || newKey == RSS_TAG_DEFAULT) { + userRssRules[newKey] = newValues; + continue; + } else { + fprintf(stderr, "Warning: Unsupported key:'%s%s'\n", + RSS_RULES_BASE, newKey.toLatin1().constData()); + continue; + } + } + } + + QStringList newValues; + foreach(QString item, project->values(RSS_RULES)) { + // If there is no stringlist defined for a rule, use rule value directly + // This is convenience for defining single line statements + if (project->values(item).isEmpty()) { + newValues << item; + } else { + newValues << project->values(item); + } + } + userRssRules[RSS_TAG_DEFAULT] << newValues; + + // Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist + // or neither of them exist + if (!((numberOfIcons.isEmpty() && iconFile.isEmpty()) || + (!numberOfIcons.isEmpty() && !iconFile.isEmpty()))) { + numberOfIcons.clear(); + iconFile.clear(); + fprintf(stderr, "Warning: Both or neither of '%s%s' and '%s%s' keys must exist.\n", + RSS_RULES_BASE, RSS_TAG_NBROFICONS, RSS_RULES_BASE, RSS_TAG_ICONFILE); + } + + // Validate that RSS_TAG_NBROFICONS contains only numbers + if (!numberOfIcons.isEmpty()) { + bool ok; + numberOfIcons = numberOfIcons.simplified(); + numberOfIcons.toInt(&ok); + if (!ok) { + numberOfIcons.clear(); + iconFile.clear(); + fprintf(stderr, "Warning: '%s%s' must be integer in decimal format.\n", + RSS_RULES_BASE, RSS_TAG_NBROFICONS); + } + } +} + +void SymbianCommonGenerator::writeCustomDefFile() +{ + if (targetType == TypePlugin && !generator->project->isActiveConfig("stdbinary")) { + // Create custom def file for plugin + QFile ft(Option::output_dir + QLatin1Char('/') + QLatin1String(PLUGIN_COMMON_DEF_FILE_ACTUAL)); + + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t(&ft); + + t << "; ==============================================================================" << endl; + t << "; Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; + t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; + t << "; This file is generated by qmake and should not be modified by the" << endl; + t << "; user." << endl; + t << "; Name : " PLUGIN_COMMON_DEF_FILE_ACTUAL << endl; + t << "; Part of : " << generator->project->values("TARGET").join(" ") << endl; + t << "; Description : Fixes common plugin symbols to known ordinals" << endl; + t << "; Version : " << endl; + t << ";" << endl; + t << "; ==============================================================================" << "\n" << endl; + + t << endl; + + t << "EXPORTS" << endl; + t << "\tqt_plugin_query_verification_data @ 1 NONAME" << endl; + t << "\tqt_plugin_instance @ 2 NONAME" << endl; + t << endl; + } else { + PRINT_FILE_CREATE_ERROR(QString(PLUGIN_COMMON_DEF_FILE_ACTUAL)) + } + } +} + +QStringList SymbianCommonGenerator::symbianLangCodesFromTsFiles() +{ + QStringList tsfiles; + QStringList symbianLangCodes; + tsfiles << generator->project->values("TRANSLATIONS"); + + fillQt2S60LangMapTable(); + + foreach(QString file, tsfiles) { + int extIndex = file.lastIndexOf("."); + int langIndex = file.lastIndexOf("_", (extIndex - file.length())); + langIndex += 1; + QString qtlang = file.mid(langIndex, extIndex - langIndex); + QString s60lang = qt2S60LangMapTable.value(qtlang, QString("SC")); + + if (!symbianLangCodes.contains(s60lang) && s60lang != "SC") + symbianLangCodes += s60lang; + } + + return symbianLangCodes; +} + +void SymbianCommonGenerator::fillQt2S60LangMapTable() +{ + qt2S60LangMapTable.reserve(170); // 165 items at time of writing. + qt2S60LangMapTable.insert("ab", "SC"); //Abkhazian // + qt2S60LangMapTable.insert("om", "SC"); //Afan // + qt2S60LangMapTable.insert("aa", "SC"); //Afar // + qt2S60LangMapTable.insert("af", "34"); //Afrikaans //Afrikaans + qt2S60LangMapTable.insert("sq", "35"); //Albanian //Albanian + qt2S60LangMapTable.insert("am", "36"); //Amharic //Amharic + qt2S60LangMapTable.insert("ar", "37"); //Arabic //Arabic + qt2S60LangMapTable.insert("hy", "38"); //Armenian //Armenian + qt2S60LangMapTable.insert("as", "SC"); //Assamese // + qt2S60LangMapTable.insert("ay", "SC"); //Aymara // + qt2S60LangMapTable.insert("az", "SC"); //Azerbaijani // + qt2S60LangMapTable.insert("ba", "SC"); //Bashkir // + qt2S60LangMapTable.insert("eu", "SC"); //Basque // + qt2S60LangMapTable.insert("bn", "41"); //Bengali //Bengali + qt2S60LangMapTable.insert("dz", "SC"); //Bhutani // + qt2S60LangMapTable.insert("bh", "SC"); //Bihari // + qt2S60LangMapTable.insert("bi", "SC"); //Bislama // + qt2S60LangMapTable.insert("br", "SC"); //Breton // + qt2S60LangMapTable.insert("bg", "42"); //Bulgarian //Bulgarian + qt2S60LangMapTable.insert("my", "43"); //Burmese //Burmese + qt2S60LangMapTable.insert("be", "40"); //Byelorussian //Belarussian + qt2S60LangMapTable.insert("km", "SC"); //Cambodian // + qt2S60LangMapTable.insert("ca", "44"); //Catalan //Catalan + qt2S60LangMapTable.insert("zh", "SC"); //Chinese // + qt2S60LangMapTable.insert("co", "SC"); //Corsican // + qt2S60LangMapTable.insert("hr", "45"); //Croatian //Croatian + qt2S60LangMapTable.insert("cs", "25"); //Czech //Czech + qt2S60LangMapTable.insert("da", "07"); //Danish //Danish + qt2S60LangMapTable.insert("nl", "18"); //Dutch //Dutch + qt2S60LangMapTable.insert("en", "01"); //English //English(UK) + qt2S60LangMapTable.insert("eo", "SC"); //Esperanto // + qt2S60LangMapTable.insert("et", "49"); //Estonian //Estonian + qt2S60LangMapTable.insert("fo", "SC"); //Faroese // + qt2S60LangMapTable.insert("fj", "SC"); //Fiji // + qt2S60LangMapTable.insert("fi", "09"); //Finnish //Finnish + qt2S60LangMapTable.insert("fr", "02"); //French //French + qt2S60LangMapTable.insert("fy", "SC"); //Frisian // + qt2S60LangMapTable.insert("gd", "52"); //Gaelic //Gaelic + qt2S60LangMapTable.insert("gl", "SC"); //Galician // + qt2S60LangMapTable.insert("ka", "53"); //Georgian //Georgian + qt2S60LangMapTable.insert("de", "03"); //German //German + qt2S60LangMapTable.insert("el", "54"); //Greek //Greek + qt2S60LangMapTable.insert("kl", "SC"); //Greenlandic // + qt2S60LangMapTable.insert("gn", "SC"); //Guarani // + qt2S60LangMapTable.insert("gu", "56"); //Gujarati //Gujarati + qt2S60LangMapTable.insert("ha", "SC"); //Hausa // + qt2S60LangMapTable.insert("he", "57"); //Hebrew //Hebrew + qt2S60LangMapTable.insert("hi", "58"); //Hindi //Hindi + qt2S60LangMapTable.insert("hu", "17"); //Hungarian //Hungarian + qt2S60LangMapTable.insert("is", "15"); //Icelandic //Icelandic + qt2S60LangMapTable.insert("id", "59"); //Indonesian //Indonesian + qt2S60LangMapTable.insert("ia", "SC"); //Interlingua // + qt2S60LangMapTable.insert("ie", "SC"); //Interlingue // + qt2S60LangMapTable.insert("iu", "SC"); //Inuktitut // + qt2S60LangMapTable.insert("ik", "SC"); //Inupiak // + qt2S60LangMapTable.insert("ga", "60"); //Irish //Irish + qt2S60LangMapTable.insert("it", "05"); //Italian //Italian + qt2S60LangMapTable.insert("ja", "32"); //Japanese //Japanese + qt2S60LangMapTable.insert("jv", "SC"); //Javanese // + qt2S60LangMapTable.insert("kn", "62"); //Kannada //Kannada + qt2S60LangMapTable.insert("ks", "SC"); //Kashmiri // + qt2S60LangMapTable.insert("kk", "63"); //Kazakh //Kazakh + qt2S60LangMapTable.insert("rw", "SC"); //Kinyarwanda // + qt2S60LangMapTable.insert("ky", "SC"); //Kirghiz // + qt2S60LangMapTable.insert("ko", "65"); //Korean //Korean + qt2S60LangMapTable.insert("ku", "SC"); //Kurdish // + qt2S60LangMapTable.insert("rn", "SC"); //Kurundi // + qt2S60LangMapTable.insert("lo", "66"); //Laothian //Laothian + qt2S60LangMapTable.insert("la", "SC"); //Latin // + qt2S60LangMapTable.insert("lv", "67"); //Latvian //Latvian + qt2S60LangMapTable.insert("ln", "SC"); //Lingala // + qt2S60LangMapTable.insert("lt", "68"); //Lithuanian //Lithuanian + qt2S60LangMapTable.insert("mk", "69"); //Macedonian //Macedonian + qt2S60LangMapTable.insert("mg", "SC"); //Malagasy // + qt2S60LangMapTable.insert("ms", "70"); //Malay //Malay + qt2S60LangMapTable.insert("ml", "71"); //Malayalam //Malayalam + qt2S60LangMapTable.insert("mt", "SC"); //Maltese // + qt2S60LangMapTable.insert("mi", "SC"); //Maori // + qt2S60LangMapTable.insert("mr", "72"); //Marathi //Marathi + qt2S60LangMapTable.insert("mo", "73"); //Moldavian //Moldovian + qt2S60LangMapTable.insert("mn", "74"); //Mongolian //Mongolian + qt2S60LangMapTable.insert("na", "SC"); //Nauru // + qt2S60LangMapTable.insert("ne", "SC"); //Nepali // + qt2S60LangMapTable.insert("nb", "08"); //Norwegian //Norwegian + qt2S60LangMapTable.insert("oc", "SC"); //Occitan // + qt2S60LangMapTable.insert("or", "SC"); //Oriya // + qt2S60LangMapTable.insert("ps", "SC"); //Pashto // + qt2S60LangMapTable.insert("fa", "SC"); //Persian // + qt2S60LangMapTable.insert("pl", "27"); //Polish //Polish + qt2S60LangMapTable.insert("pt", "13"); //Portuguese //Portuguese + qt2S60LangMapTable.insert("pa", "77"); //Punjabi //Punjabi + qt2S60LangMapTable.insert("qu", "SC"); //Quechua // + qt2S60LangMapTable.insert("rm", "SC"); //RhaetoRomance // + qt2S60LangMapTable.insert("ro", "78"); //Romanian //Romanian + qt2S60LangMapTable.insert("ru", "16"); //Russian //Russian + qt2S60LangMapTable.insert("sm", "SC"); //Samoan // + qt2S60LangMapTable.insert("sg", "SC"); //Sangho // + qt2S60LangMapTable.insert("sa", "SC"); //Sanskrit // + qt2S60LangMapTable.insert("sr", "79"); //Serbian //Serbian + qt2S60LangMapTable.insert("sh", "SC"); //SerboCroatian // + qt2S60LangMapTable.insert("st", "SC"); //Sesotho // + qt2S60LangMapTable.insert("tn", "SC"); //Setswana // + qt2S60LangMapTable.insert("sn", "SC"); //Shona // + qt2S60LangMapTable.insert("sd", "SC"); //Sindhi // + qt2S60LangMapTable.insert("si", "80"); //Singhalese //Sinhalese + qt2S60LangMapTable.insert("ss", "SC"); //Siswati // + qt2S60LangMapTable.insert("sk", "26"); //Slovak //Slovak + qt2S60LangMapTable.insert("sl", "28"); //Slovenian //Slovenian + qt2S60LangMapTable.insert("so", "81"); //Somali //Somali + qt2S60LangMapTable.insert("es", "04"); //Spanish //Spanish + qt2S60LangMapTable.insert("su", "SC"); //Sundanese // + qt2S60LangMapTable.insert("sw", "84"); //Swahili //Swahili + qt2S60LangMapTable.insert("sv", "06"); //Swedish //Swedish + qt2S60LangMapTable.insert("tl", "39"); //Tagalog //Tagalog + qt2S60LangMapTable.insert("tg", "SC"); //Tajik // + qt2S60LangMapTable.insert("ta", "87"); //Tamil //Tamil + qt2S60LangMapTable.insert("tt", "SC"); //Tatar // + qt2S60LangMapTable.insert("te", "88"); //Telugu //Telugu + qt2S60LangMapTable.insert("th", "33"); //Thai //Thai + qt2S60LangMapTable.insert("bo", "89"); //Tibetan //Tibetan + qt2S60LangMapTable.insert("ti", "90"); //Tigrinya //Tigrinya + qt2S60LangMapTable.insert("to", "SC"); //Tonga // + qt2S60LangMapTable.insert("ts", "SC"); //Tsonga // + qt2S60LangMapTable.insert("tr", "14"); //Turkish //Turkish + qt2S60LangMapTable.insert("tk", "92"); //Turkmen //Turkmen + qt2S60LangMapTable.insert("tw", "SC"); //Twi // + qt2S60LangMapTable.insert("ug", "SC"); //Uigur // + qt2S60LangMapTable.insert("uk", "93"); //Ukrainian //Ukrainian + qt2S60LangMapTable.insert("ur", "94"); //Urdu //Urdu + qt2S60LangMapTable.insert("uz", "SC"); //Uzbek // + qt2S60LangMapTable.insert("vi", "96"); //Vietnamese //Vietnamese + qt2S60LangMapTable.insert("vo", "SC"); //Volapuk // + qt2S60LangMapTable.insert("cy", "97"); //Welsh //Welsh + qt2S60LangMapTable.insert("wo", "SC"); //Wolof // + qt2S60LangMapTable.insert("xh", "SC"); //Xhosa // + qt2S60LangMapTable.insert("yi", "SC"); //Yiddish // + qt2S60LangMapTable.insert("yo", "SC"); //Yoruba // + qt2S60LangMapTable.insert("za", "SC"); //Zhuang // + qt2S60LangMapTable.insert("zu", "98"); //Zulu //Zulu + qt2S60LangMapTable.insert("nn", "75"); //Nynorsk //NorwegianNynorsk + qt2S60LangMapTable.insert("bs", "SC"); //Bosnian // + qt2S60LangMapTable.insert("dv", "SC"); //Divehi // + qt2S60LangMapTable.insert("gv", "SC"); //Manx // + qt2S60LangMapTable.insert("kw", "SC"); //Cornish // + qt2S60LangMapTable.insert("ak", "SC"); //Akan // + qt2S60LangMapTable.insert("kok", "SC"); //Konkani // + qt2S60LangMapTable.insert("gaa", "SC"); //Ga // + qt2S60LangMapTable.insert("ig", "SC"); //Igbo // + qt2S60LangMapTable.insert("kam", "SC"); //Kamba // + qt2S60LangMapTable.insert("syr", "SC"); //Syriac // + qt2S60LangMapTable.insert("byn", "SC"); //Blin // + qt2S60LangMapTable.insert("gez", "SC"); //Geez // + qt2S60LangMapTable.insert("kfo", "SC"); //Koro // + qt2S60LangMapTable.insert("sid", "SC"); //Sidamo // + qt2S60LangMapTable.insert("cch", "SC"); //Atsam // + qt2S60LangMapTable.insert("tig", "SC"); //Tigre // + qt2S60LangMapTable.insert("kaj", "SC"); //Jju // + qt2S60LangMapTable.insert("fur", "SC"); //Friulian // + qt2S60LangMapTable.insert("ve", "SC"); //Venda // + qt2S60LangMapTable.insert("ee", "SC"); //Ewe // + qt2S60LangMapTable.insert("wa", "SC"); //Walamo // + qt2S60LangMapTable.insert("haw", "SC"); //Hawaiian // + qt2S60LangMapTable.insert("kcg", "SC"); //Tyap // + qt2S60LangMapTable.insert("ny", "SC"); //Chewa // +} + diff --git a/qmake/generators/symbian/symbiancommon.h b/qmake/generators/symbian/symbiancommon.h new file mode 100644 index 0000000000..dae1e4aa50 --- /dev/null +++ b/qmake/generators/symbian/symbiancommon.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SYMBIANCOMMON_H +#define SYMBIANCOMMON_H + +#include <project.h> +#include <makefile.h> +#include "initprojectdeploy_symbian.h" + +#define PRINT_FILE_CREATE_ERROR(filename) fprintf(stderr, "Error: Could not create '%s'\n", qPrintable(filename)); + +class SymbianCommonGenerator +{ +public: + enum TargetType { + TypeExe, + TypeDll, + TypeLib, + TypePlugin, + TypeSubdirs + }; + + SymbianCommonGenerator(MakefileGenerator *generator); + + virtual void init(); + +protected: + + QString removePathSeparators(QString &file); + void removeSpecialCharacters(QString& str); + void removeEpocSpecialCharacters(QString& str); + void generatePkgFile(const QString &iconFile, bool epocBuild); + bool containsStartWithItem(const QChar &c, const QStringList& src); + + void writeRegRssFile(QMap<QString, QStringList> &useritems); + void writeRegRssList(QTextStream &t, QStringList &userList, + const QString &listTag, + const QString &listItem); + void writeRssFile(QString &numberOfIcons, QString &iconfile); + void writeLocFile(QStringList &symbianLangCodes); + void readRssRules(QString &numberOfIcons, + QString &iconFile, + QMap<QString, QStringList> &userRssRules); + + void writeCustomDefFile(); + + QStringList symbianLangCodesFromTsFiles(); + void fillQt2S60LangMapTable(); + +protected: + MakefileGenerator *generator; + + QStringList generatedFiles; + QStringList generatedDirs; + QString fixedTarget; + QString privateDirUid; + QString uid3; + TargetType targetType; + + QHash<QString, QString> qt2S60LangMapTable; +}; + +#endif // SYMBIANCOMMON_H diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp index 40ef934d58..cf6bd1388e 100644 --- a/qmake/generators/symbian/symmake.cpp +++ b/qmake/generators/symbian/symmake.cpp @@ -53,10 +53,9 @@ #include <symbian/epocroot.h> #define RESOURCE_DIRECTORY_MMP "/resource/apps" -#define RESOURCE_DIRECTORY_RESOURCE "\\\\resource\\\\apps\\\\" #define REGISTRATION_RESOURCE_DIRECTORY_HW "/private/10003a3f/import/apps" #define PLUGIN_COMMON_DEF_FILE_FOR_MMP "./plugin_common.def" -#define PLUGIN_COMMON_DEF_FILE_ACTUAL "plugin_commonU.def" +#define BLD_INF_FILENAME_LEN (sizeof(BLD_INF_FILENAME) - 1) #define BLD_INF_RULES_BASE "BLD_INF_RULES." #define BLD_INF_TAG_PLATFORMS "prj_platforms" @@ -65,17 +64,6 @@ #define BLD_INF_TAG_EXTENSIONS "prj_extensions" #define BLD_INF_TAG_TESTEXTENSIONS "prj_testextensions" -#define RSS_RULES "RSS_RULES" -#define RSS_RULES_BASE "RSS_RULES." -#define RSS_TAG_NBROFICONS "number_of_icons" -#define RSS_TAG_ICONFILE "icon_file" -#define RSS_TAG_HEADER "header" -#define RSS_TAG_SERVICE_LIST "service_list" -#define RSS_TAG_FILE_OWNERSHIP_LIST "file_ownership_list" -#define RSS_TAG_DATATYPE_LIST "datatype_list" -#define RSS_TAG_FOOTER "footer" -#define RSS_TAG_DEFAULT "default_rules" // Same as just giving rules without tag - #define MMP_TARGET "TARGET" #define MMP_TARGETTYPE "TARGETTYPE" #define MMP_SECUREID "SECUREID" @@ -95,22 +83,6 @@ #define VAR_CFLAGS "QMAKE_CFLAGS" #define VAR_LFLAGS "QMAKE_LFLAGS" -#define SIS_TARGET "sis" -#define INSTALLER_SIS_TARGET "installer_sis" -#define ROM_STUB_SIS_TARGET "stub_sis" -#define OK_SIS_TARGET "ok_sis" -#define OK_INSTALLER_SIS_TARGET "ok_installer_sis" -#define OK_ROM_STUB_SIS_TARGET "ok_stub_sis" -#define FAIL_SIS_NOPKG_TARGET "fail_sis_nopkg" -#define FAIL_SIS_NOCACHE_TARGET "fail_sis_nocache" - -#define PRINT_FILE_CREATE_ERROR(filename) fprintf(stderr, "Error: Could not create '%s'\n", qPrintable(filename)); - -#define MANUFACTURER_NOTE_FILE "manufacturer_note.txt" -#define DEFAULT_MANUFACTURER_NOTE \ - "The package is not supported for devices from this manufacturer. Please try the selfsigned " \ - "version of the package instead." - QString SymbianMakefileGenerator::fixPathForMmp(const QString& origPath, const QDir& parentDir) { static QString epocRootStr; @@ -168,7 +140,7 @@ QString SymbianMakefileGenerator::absolutizePath(const QString& origPath) return resultPath; } -SymbianMakefileGenerator::SymbianMakefileGenerator() : MakefileGenerator() { } +SymbianMakefileGenerator::SymbianMakefileGenerator() : MakefileGenerator(), SymbianCommonGenerator(this) { } SymbianMakefileGenerator::~SymbianMakefileGenerator() { } void SymbianMakefileGenerator::writeHeader(QTextStream &t) @@ -195,13 +167,19 @@ void SymbianMakefileGenerator::writeHeader(QTextStream &t) bldinfDefine.append(generate_uid(project->projectFile())); bldinfDefine.prepend("BLD_INF_"); - removeSpecialCharacters(bldinfDefine); + removeEpocSpecialCharacters(bldinfDefine); t << "#define " << bldinfDefine.toUpper() << endl << endl; } bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) { + if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { + fprintf(stderr, "Project files not generated because all requirements are not met:\n\t%s\n", + qPrintable(var("QMAKE_FAILED_REQUIREMENTS"))); + return false; + } + writeHeader(t); QString numberOfIcons; @@ -214,7 +192,6 @@ bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) // Generate pkg files if there are any actual files to deploy bool generatePkg = false; - DeploymentList depList; if (targetType == TypeExe) { generatePkg = true; @@ -228,15 +205,15 @@ bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) } if (generatePkg) { - generatePkgFile(iconFile, depList); + generatePkgFile(iconFile, true); } - writeBldInfContent(t, generatePkg, iconFile, depList); + writeBldInfContent(t, generatePkg, iconFile); // Generate empty wrapper makefile here, because wrapper makefile must exist before writeMkFile, // but all required data is not yet available. bool isPrimaryMakefile = true; - QString wrapperFileName("Makefile"); + QString wrapperFileName = Option::output_dir + QLatin1Char('/') + QLatin1String("Makefile"); QString outputFileName = fileInfo(Option::output.fileName()).fileName(); if (outputFileName != BLD_INF_FILENAME) { wrapperFileName.append(".").append(outputFileName.startsWith(BLD_INF_FILENAME) @@ -264,15 +241,8 @@ bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) writeMkFile(wrapperFileName, false); - QString shortProFilename = project->projectFile(); - shortProFilename.replace(0, shortProFilename.lastIndexOf("/") + 1, QString("")); - shortProFilename.replace(Option::pro_ext, QString("")); - - QString mmpFilename = shortProFilename; - mmpFilename.append("_"); - mmpFilename.append(uid3); - mmpFilename.append(Option::mmp_ext); - writeMmpFile(mmpFilename, symbianLangCodes); + QString absoluteMmpFileName = Option::output_dir + QLatin1Char('/') + mmpFileName; + writeMmpFile(absoluteMmpFileName, symbianLangCodes); if (targetType == TypeExe) { if (!project->isActiveConfig("no_icon")) { @@ -288,339 +258,10 @@ bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) return true; } -void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, DeploymentList &depList) -{ - QString pkgFilename = QString("%1_template.%2") - .arg(fixedTarget) - .arg("pkg"); - QFile pkgFile(pkgFilename); - if (!pkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - PRINT_FILE_CREATE_ERROR(pkgFilename); - return; - } - - generatedFiles << pkgFile.fileName(); - QTextStream t(&pkgFile); - - QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n"); - if (installerSisHeader.isEmpty()) - installerSisHeader = "0xA000D7CE"; // Use default self-signable UID if not defined - - QString wrapperStreamBuffer; - QTextStream tw(&wrapperStreamBuffer); - - QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate); - - // Header info - QString wrapperPkgFilename = QString("%1_installer.%2") - .arg(fixedTarget) - .arg("pkg"); - QString headerComment = "; %1 generated by qmake at %2\n" - "; This file is generated by qmake and should not be modified by the user\n" - ";\n\n"; - t << headerComment.arg(pkgFilename).arg(dateStr); - tw << headerComment.arg(wrapperPkgFilename).arg(dateStr); - - // Construct QStringList from pkg_prerules since we need search it before printed to file - // Note: Though there can't be more than one language or header line, use stringlists - // in case user wants comments to go with the rules. - QStringList rawPkgPreRules; - QStringList languageRules; - QStringList headerRules; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line mmp statements - if (pkgrulesValue.isEmpty()) { - if (pkgrulesItem.startsWith("&")) - languageRules << pkgrulesItem; - else if (pkgrulesItem.startsWith("#")) - headerRules << pkgrulesItem; - else - rawPkgPreRules << pkgrulesItem; - } else { - if (containsStartWithItem('&', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - languageRules << pkgrule; - } - } else if (containsStartWithItem('#', pkgrulesValue)) { - foreach(QString pkgrule, pkgrulesValue) { - headerRules << pkgrule; - } - } else { - foreach(QString pkgrule, pkgrulesValue) { - rawPkgPreRules << pkgrule; - } - } - } - } - } - - // Apply some defaults if specific data does not exist in PKG pre-rules - - if (languageRules.isEmpty()) { - // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS) - languageRules << "; Language\n&EN\n\n"; - } else if (headerRules.isEmpty()) { - // In case user defines langs, he must take care also about SIS header - fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n"); - } - - t << languageRules.join("\n") << endl; - tw << languageRules.join("\n") << endl; - - // name of application, UID and version - QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ','); - QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n"; - QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET"))); - visualTarget = removePathSeparators(visualTarget); - QString wrapperTarget = visualTarget + " installer"; - - if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) { - tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion); - } else { - tw << installerSisHeader << endl; - } - - if (headerRules.isEmpty()) - t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion); - else - t << headerRules.join("\n") << endl; - - // Localized vendor name - QString vendorName; - if (!containsStartWithItem('%', rawPkgPreRules)) { - vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n"; - } - - // Unique vendor name - if (!containsStartWithItem(':', rawPkgPreRules)) { - vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n"; - } - - t << vendorName; - tw << vendorName; - - // PKG pre-rules - these are added before actual file installations i.e. SIS package body - if (rawPkgPreRules.size()) { - QString comment = "\n; Manual PKG pre-rules from PRO files\n"; - t << comment; - tw << comment; - - foreach(QString item, rawPkgPreRules) { - // Only regular pkg file should have package dependencies or pkg header if that is - // defined using prerules. - if (!item.startsWith("(") && !item.startsWith("#")) { - tw << item << endl; - } - t << item << endl; - } - t << endl; - tw << endl; - } - - // Begin Manufacturer block - if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { - QString manufacturerStr("IF "); - foreach(QString manufacturer, project->values("DEPLOYMENT.manufacturers")) { - manufacturerStr.append(QString("(MANUFACTURER)=(%1) OR \n ").arg(manufacturer)); - } - // Remove the final OR - manufacturerStr.chop(8); - t << manufacturerStr << endl; - } - - // Install paths on the phone *** should be dynamic at some point - QString installPathBin = "!:\\sys\\bin"; - QString installPathResource = "!:\\resource\\apps"; - QString installPathRegResource = "!:\\private\\10003a3f\\import\\apps"; - - // Find location of builds - QString epocReleasePath = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)") - .arg(epocRoot()); - - if (targetType == TypeExe) { - // deploy .exe file - t << "; Executable and default resource files" << endl; - QString exeFile = fixedTarget + ".exe"; - t << QString("\"%1/%2\" - \"%3\\%4\"") - .arg(epocReleasePath) - .arg(exeFile) - .arg(installPathBin) - .arg(exeFile) << endl; - - // deploy rsc & reg_rsc file - if (!project->isActiveConfig("no_icon")) { - t << QString("\"%1epoc32/data/z/resource/apps/%2\" - \"%3\\%4\"") - .arg(epocRoot()) - .arg(fixedTarget + ".rsc") - .arg(installPathResource) - .arg(fixedTarget + ".rsc") << endl; - - t << QString("\"%1epoc32/data/z/private/10003a3f/import/apps/%2\" - \"%3\\%4\"") - .arg(epocRoot()) - .arg(fixedTarget + "_reg.rsc") - .arg(installPathRegResource) - .arg(fixedTarget + "_reg.rsc") << endl; - - if (!iconFile.isEmpty()) { - t << QString("\"%1epoc32/data/z%2\" - \"!:%3\"") - .arg(epocRoot()) - .arg(iconFile) - .arg(QDir::toNativeSeparators(iconFile)) << endl << endl; - } - } - } - - // deploy any additional DEPLOYMENT files - QString remoteTestPath; - remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid); - QString zDir = epocRoot() + QLatin1String("epoc32/data/z"); - - initProjectDeploySymbian(project, depList, remoteTestPath, true, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles); - if (depList.size()) - t << "; DEPLOYMENT" << endl; - for (int i = 0; i < depList.size(); ++i) { - QString from = depList.at(i).from; - QString to = depList.at(i).to; - - // Deploy anything not already deployed from under epoc32 instead from under - // \epoc32\data\z\ to enable using pkg file without rebuilding - // the project, which can be useful for some binary only distributions. - if (!from.contains(QLatin1String("epoc32"), Qt::CaseInsensitive)) { - from = to; - if (from.size() > 1 && from.at(1) == QLatin1Char(':')) - from = from.mid(2); - from.prepend(zDir); - } else { - if (from.size() > 1 && from.at(1) == QLatin1Char(':')) - from = from.mid(2); - } - - t << QString("\"%1\" - \"%2\"").arg(from.replace('\\','/')).arg(to) << endl; - } - t << endl; - - // PKG post-rules - these are added after actual file installations i.e. SIS package body - t << "; Manual PKG post-rules from PRO files" << endl; - foreach(QString deploymentItem, project->values("DEPLOYMENT")) { - foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_postrules")) { - QStringList pkgrulesValue = project->values(pkgrulesItem); - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line statements - if (pkgrulesValue.isEmpty()) { - t << pkgrulesItem << endl; - } else { - foreach(QString pkgrule, pkgrulesValue) { - t << pkgrule << endl; - } - } - t << endl; - } - } - - // Close Manufacturer block - if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { - QString manufacturerFailNoteFile; - if (project->values("DEPLOYMENT.manufacturers.fail_note").isEmpty()) { - manufacturerFailNoteFile = QString("%1_" MANUFACTURER_NOTE_FILE).arg(uid3); - QFile ft(manufacturerFailNoteFile); - if (ft.open(QIODevice::WriteOnly)) { - generatedFiles << ft.fileName(); - QTextStream t2(&ft); - - t2 << QString(DEFAULT_MANUFACTURER_NOTE) << endl; - } else { - PRINT_FILE_CREATE_ERROR(manufacturerFailNoteFile) - } - } else { - manufacturerFailNoteFile = project->values("DEPLOYMENT.manufacturers.fail_note").join(""); - } - - t << "ELSEIF NOT(0) ; MANUFACTURER" << endl - << "\"" << fileInfo(manufacturerFailNoteFile).absoluteFilePath() << "\"" - << " - \"\", FILETEXT, TEXTEXIT" << endl - << "ENDIF ; MANUFACTURER" << endl; - } - - // Write wrapper pkg - if (!installerSisHeader.isEmpty()) { - QFile wrapperPkgFile(wrapperPkgFilename); - if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - PRINT_FILE_CREATE_ERROR(wrapperPkgFilename); - return; - } - - generatedFiles << wrapperPkgFile.fileName(); - QTextStream twf(&wrapperPkgFile); - - twf << wrapperStreamBuffer << endl; - - // Wrapped files deployment - QString currentPath = qmake_getpwd(); - QString sisName = QString("%1.sis").arg(fixedTarget); - twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\adm\\" << sisName << "\"" << endl; - - QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath); - bootStrapPath.append("/smartinstaller.sis"); - QFileInfo fi(fileInfo(bootStrapPath)); - twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl; - } -} - -bool SymbianMakefileGenerator::containsStartWithItem(const QChar &c, const QStringList& src) -{ - bool result = false; - foreach(QString str, src) { - if (str.startsWith(c)) { - result = true; - break; - } - } - return result; -} - -void SymbianMakefileGenerator::writeCustomDefFile() -{ - if (targetType == TypePlugin && !project->isActiveConfig("stdbinary")) { - // Create custom def file for plugin - QFile ft(QLatin1String(PLUGIN_COMMON_DEF_FILE_ACTUAL)); - - if (ft.open(QIODevice::WriteOnly)) { - generatedFiles << ft.fileName(); - QTextStream t(&ft); - - t << "; ==============================================================================" << endl; - t << "; Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; - t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; - t << "; This file is generated by qmake and should not be modified by the" << endl; - t << "; user." << endl; - t << "; Name : " PLUGIN_COMMON_DEF_FILE_ACTUAL << endl; - t << "; Part of : " << project->values("TARGET").join(" ") << endl; - t << "; Description : Fixes common plugin symbols to known ordinals" << endl; - t << "; Version : " << endl; - t << ";" << endl; - t << "; ==============================================================================" << "\n" << endl; - - t << endl; - - t << "EXPORTS" << endl; - t << "\tqt_plugin_query_verification_data @ 1 NONAME" << endl; - t << "\tqt_plugin_instance @ 2 NONAME" << endl; - t << endl; - } else { - PRINT_FILE_CREATE_ERROR(QString(PLUGIN_COMMON_DEF_FILE_ACTUAL)) - } - } -} - void SymbianMakefileGenerator::init() { MakefileGenerator::init(); - fixedTarget = escapeFilePath(fileFixify(project->first("TARGET"))); - fixedTarget = removePathSeparators(fixedTarget); - removeSpecialCharacters(fixedTarget); + SymbianCommonGenerator::init(); if (0 != project->values("QMAKE_PLATFORM").size()) platform = varGlue("QMAKE_PLATFORM", "", " ", ""); @@ -635,62 +276,20 @@ void SymbianMakefileGenerator::init() project->values("MAKEFILE") += BLD_INF_FILENAME; // .mmp - initMmpVariables(); + mmpFileName = fixedTarget; + if (targetType == TypeExe) + mmpFileName.append("_exe"); + else if (targetType == TypeDll || targetType == TypePlugin) + mmpFileName.append("_dll"); + else if (targetType == TypeLib) + mmpFileName.append("_lib"); + mmpFileName.append(Option::mmp_ext); - // Check TARGET.UID3 presence - if (0 != project->values("TARGET.UID3").size()) { - uid3 = project->first("TARGET.UID3"); - } else { - uid3 = generateUID3(); - } - - if ((project->values("TEMPLATE")).contains("app")) - targetType = TypeExe; - else if ((project->values("TEMPLATE")).contains("lib")) { - // Check CONFIG to see if we are to build staticlib or dll - if (project->isActiveConfig("staticlib") || project->isActiveConfig("static")) - targetType = TypeLib; - else if (project->isActiveConfig("plugin")) - targetType = TypePlugin; - else - targetType = TypeDll; - } else { - targetType = TypeSubdirs; - } + initMmpVariables(); - if (0 != project->values("TARGET.UID2").size()) { - uid2 = project->first("TARGET.UID2"); - } else if (project->isActiveConfig("stdbinary")) { - uid2 = "0x20004C45"; - } else { - if (targetType == TypeExe) { - if (project->values("QT").contains("gui", Qt::CaseInsensitive)) { - // exe and gui -> uid2 needed - uid2 = "0x100039CE"; - } else { - // exe but not gui: uid2 is ignored anyway -> set it to 0 - uid2 = "0"; - } - } else if (targetType == TypeDll || targetType == TypeLib || targetType == TypePlugin) { - uid2 = "0x1000008d"; - } - } + uid2 = project->first("TARGET.UID2"); uid2 = uid2.trimmed(); - uid3 = uid3.trimmed(); - - // UID is valid as either hex or decimal, so just convert it to number and back to hex - // to get proper string for private dir - bool conversionOk = false; - uint uidNum = uid3.toUInt(&conversionOk, 0); - - if (!conversionOk) { - fprintf(stderr, "Error: Invalid UID \"%s\".\n", uid3.toUtf8().constData()); - } else { - privateDirUid.setNum(uidNum, 16); - while (privateDirUid.length() < 8) - privateDirUid.insert(0, QLatin1Char('0')); - } } QString SymbianMakefileGenerator::getTargetExtension() @@ -885,7 +484,7 @@ void SymbianMakefileGenerator::writeMmpFileHeader(QTextStream &t) t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; t << "// This file is generated by qmake and should not be modified by the" << endl; t << "// user." << endl; - t << "// Name : " << escapeFilePath(fileFixify(project->projectFile().remove(project->projectFile().length() - 4, 4))) << Option::mmp_ext << endl; + t << "// Name : " << mmpFileName << endl; t << "// ==============================================================================" << endl << endl; } @@ -1264,7 +863,7 @@ void SymbianMakefileGenerator::writeMmpFileRulesPart(QTextStream& t) } } -void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploymentExtension, const QString &iconFile, DeploymentList &depList) +void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploymentExtension, const QString &iconFile) { // Read user defined bld inf rules @@ -1295,8 +894,6 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy // Add includes of subdirs bld.inf files - QString mmpfilename = escapeFilePath(fileFixify(project->projectFile())); - mmpfilename = mmpfilename.replace(mmpfilename.lastIndexOf("."), 4, Option::mmp_ext); QString currentPath = qmake_getpwd(); QDir directory(currentPath); @@ -1341,7 +938,7 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy QString uid = generate_uid(fullProName); QString bldinfDefine = QString("BLD_INF_") + subdirFileName + QString("_") + uid; bldinfDefine = bldinfDefine.toUpper(); - removeSpecialCharacters(bldinfDefine); + removeEpocSpecialCharacters(bldinfDefine); if (!condition.isEmpty()) t << "#if defined(" << condition << ")" << endl; @@ -1378,15 +975,8 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy t << endl << mmpTag << endl << endl; writeBldInfMkFilePart(t, addDeploymentExtension); - if (targetType != TypeSubdirs) { - QString shortProFilename = project->projectFile(); - shortProFilename.replace(0, shortProFilename.lastIndexOf("/") + 1, QString("")); - shortProFilename.replace(Option::pro_ext, QString("")); - - QString mmpFilename = shortProFilename + QString("_") + uid3 + Option::mmp_ext; - - t << mmpFilename << endl; - } + if (targetType != TypeSubdirs) + t << mmpFileName << endl; userItems = userBldInfRules.value(mmpTag); foreach(QString item, userItems) @@ -1420,442 +1010,6 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy } } -void SymbianMakefileGenerator::writeRegRssFile(QMap<QString, QStringList> &userItems) -{ - QString filename(fixedTarget); - filename.append("_reg.rss"); - QFile ft(filename); - if (ft.open(QIODevice::WriteOnly)) { - generatedFiles << ft.fileName(); - QTextStream t(&ft); - t << "// ============================================================================" << endl; - t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; - t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; - t << "// * This file is generated by qmake and should not be modified by the" << endl; - t << "// * user." << endl; - t << "// ============================================================================" << endl; - t << endl; - t << "#include <" << fixedTarget << ".rsg>" << endl; - t << "#include <appinfo.rh>" << endl; - foreach(QString item, userItems[RSS_TAG_HEADER]) - t << item << endl; - t << endl; - t << "UID2 KUidAppRegistrationResourceFile" << endl; - t << "UID3 " << uid3 << endl << endl; - t << "RESOURCE APP_REGISTRATION_INFO" << endl; - t << "\t{" << endl; - t << "\tapp_file=\"" << fixedTarget << "\";" << endl; - t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl; - - writeRegRssList(t, userItems[RSS_TAG_SERVICE_LIST], - QLatin1String(RSS_TAG_SERVICE_LIST), - QLatin1String("SERVICE_INFO")); - writeRegRssList(t, userItems[RSS_TAG_FILE_OWNERSHIP_LIST], - QLatin1String(RSS_TAG_FILE_OWNERSHIP_LIST), - QLatin1String("FILE_OWNERSHIP_INFO")); - writeRegRssList(t, userItems[RSS_TAG_DATATYPE_LIST], - QLatin1String(RSS_TAG_DATATYPE_LIST), - QLatin1String("DATATYPE")); - t << endl; - - foreach(QString item, userItems[RSS_TAG_DEFAULT]) - t << "\t" << item.replace("\n","\n\t") << endl; - t << "\t}" << endl; - - foreach(QString item, userItems[RSS_TAG_FOOTER]) - t << item << endl; - } else { - PRINT_FILE_CREATE_ERROR(filename) - } -} - -void SymbianMakefileGenerator::writeRegRssList(QTextStream &t, - QStringList &userList, - const QString &listTag, - const QString &listItem) -{ - int itemCount = userList.count(); - if (itemCount) { - t << "\t" << listTag << " ="<< endl; - t << "\t\t{" << endl; - foreach(QString item, userList) { - t << "\t\t" << listItem << endl; - t << "\t\t\t{" << endl; - t << "\t\t\t" << item.replace("\n","\n\t\t\t") << endl; - t << "\t\t\t}"; - if (--itemCount) - t << ","; - t << endl; - } - t << "\t\t}; "<< endl; - } -} - -void SymbianMakefileGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile) -{ - QString filename(fixedTarget); - filename.append(".rss"); - QFile ft(filename); - if (ft.open(QIODevice::WriteOnly)) { - generatedFiles << ft.fileName(); - QTextStream t(&ft); - t << "// ============================================================================" << endl; - t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; - t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; - t << "// * This file is generated by qmake and should not be modified by the" << endl; - t << "// * user." << endl; - t << "// ============================================================================" << endl; - t << endl; - t << "#include <appinfo.rh>" << endl; - t << "#include \"" << fixedTarget << ".loc\"" << endl; - t << endl; - t << "RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info" << endl; - t << "\t{" << endl; - t << "\tshort_caption = STRING_r_short_caption;" << endl; - t << "\tcaption_and_icon =" << endl; - t << "\tCAPTION_AND_ICON_INFO" << endl; - t << "\t\t{" << endl; - t << "\t\tcaption = STRING_r_caption;" << endl; - - QString rssIconFile = iconFile; - rssIconFile = rssIconFile.replace("/", "\\\\"); - - if (numberOfIcons.isEmpty() || rssIconFile.isEmpty()) { - // There can be maximum one item in this tag, validated when parsed - t << "\t\tnumber_of_icons = 0;" << endl; - t << "\t\ticon_file = \"\";" << endl; - } else { - // There can be maximum one item in this tag, validated when parsed - t << "\t\tnumber_of_icons = " << numberOfIcons << ";" << endl; - t << "\t\ticon_file = \"" << rssIconFile << "\";" << endl; - } - t << "\t\t};" << endl; - t << "\t}" << endl; - t << endl; - } else { - PRINT_FILE_CREATE_ERROR(filename); - } -} - -void SymbianMakefileGenerator::writeLocFile(QStringList &symbianLangCodes) -{ - QString filename(fixedTarget); - filename.append(".loc"); - QFile ft(filename); - if (ft.open(QIODevice::WriteOnly)) { - generatedFiles << ft.fileName(); - QTextStream t(&ft); - t << "// ============================================================================" << endl; - t << "// * Generated by qmake (" << qmake_version() << ") (Qt " QT_VERSION_STR ") on: "; - t << QDateTime::currentDateTime().toString(Qt::ISODate) << endl; - t << "// * This file is generated by qmake and should not be modified by the" << endl; - t << "// * user." << endl; - t << "// ============================================================================" << endl; - t << endl; - t << "#ifdef LANGUAGE_SC" << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; - foreach(QString lang, symbianLangCodes) { - t << "#elif defined LANGUAGE_" << lang << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; - } - t << "#else" << endl; - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; - t << "#endif" << endl; - } else { - PRINT_FILE_CREATE_ERROR(filename); - } -} - -void SymbianMakefileGenerator::readRssRules(QString &numberOfIcons, - QString &iconFile, QMap<QString, - QStringList> &userRssRules) -{ - for (QMap<QString, QStringList>::iterator it = project->variables().begin(); it != project->variables().end(); ++it) { - if (it.key().startsWith(RSS_RULES_BASE)) { - QString newKey = it.key().mid(sizeof(RSS_RULES_BASE) - 1); - if (newKey.isEmpty()) { - fprintf(stderr, "Warning: Empty RSS_RULES_BASE key encountered\n"); - continue; - } - QStringList newValues; - QStringList values = it.value(); - foreach(QString item, values) { - // If there is no stringlist defined for a rule, use rule value directly - // This is convenience for defining single line statements - if (project->values(item).isEmpty()) { - newValues << item; - } else { - QStringList itemList; - foreach(QString itemRow, project->values(item)) { - itemList << itemRow; - } - newValues << itemList.join("\n"); - } - } - // Verify thet there is exactly one value in RSS_TAG_NBROFICONS - if (newKey == RSS_TAG_NBROFICONS) { - if (newValues.count() == 1) { - numberOfIcons = newValues[0]; - } else { - fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n", - RSS_RULES_BASE, RSS_TAG_NBROFICONS); - continue; - } - // Verify thet there is exactly one value in RSS_TAG_ICONFILE - } else if (newKey == RSS_TAG_ICONFILE) { - if (newValues.count() == 1) { - iconFile = newValues[0]; - } else { - fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n", - RSS_RULES_BASE, RSS_TAG_ICONFILE); - continue; - } - } else if (newKey == RSS_TAG_HEADER - || newKey == RSS_TAG_SERVICE_LIST - || newKey == RSS_TAG_FILE_OWNERSHIP_LIST - || newKey == RSS_TAG_DATATYPE_LIST - || newKey == RSS_TAG_FOOTER - || newKey == RSS_TAG_DEFAULT) { - userRssRules[newKey] = newValues; - continue; - } else { - fprintf(stderr, "Warning: Unsupported key:'%s%s'\n", - RSS_RULES_BASE, newKey.toLatin1().constData()); - continue; - } - } - } - - QStringList newValues; - foreach(QString item, project->values(RSS_RULES)) { - // If there is no stringlist defined for a rule, use rule value directly - // This is convenience for defining single line statements - if (project->values(item).isEmpty()) { - newValues << item; - } else { - newValues << project->values(item); - } - } - userRssRules[RSS_TAG_DEFAULT] << newValues; - - // Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist - // or neither of them exist - if (!((numberOfIcons.isEmpty() && iconFile.isEmpty()) || - (!numberOfIcons.isEmpty() && !iconFile.isEmpty()))) { - numberOfIcons.clear(); - iconFile.clear(); - fprintf(stderr, "Warning: Both or neither of '%s%s' and '%s%s' keys must exist.\n", - RSS_RULES_BASE, RSS_TAG_NBROFICONS, RSS_RULES_BASE, RSS_TAG_ICONFILE); - } - - // Validate that RSS_TAG_NBROFICONS contains only numbers - if (!numberOfIcons.isEmpty()) { - bool ok; - numberOfIcons = numberOfIcons.simplified(); - numberOfIcons.toInt(&ok); - if (!ok) { - numberOfIcons.clear(); - iconFile.clear(); - fprintf(stderr, "Warning: '%s%s' must be integer in decimal format.\n", - RSS_RULES_BASE, RSS_TAG_NBROFICONS); - } - } -} - -QStringList SymbianMakefileGenerator::symbianLangCodesFromTsFiles() -{ - QStringList tsfiles; - QStringList symbianLangCodes; - tsfiles << project->values("TRANSLATIONS"); - - fillQt2S60LangMapTable(); - - foreach(QString file, tsfiles) { - int extIndex = file.lastIndexOf("."); - int langIndex = file.lastIndexOf("_", (extIndex - file.length())); - langIndex += 1; - QString qtlang = file.mid(langIndex, extIndex - langIndex); - QString s60lang = qt2S60LangMapTable.value(qtlang, QString("SC")); - - if (!symbianLangCodes.contains(s60lang) && s60lang != "SC") - symbianLangCodes += s60lang; - } - - return symbianLangCodes; -} - -void SymbianMakefileGenerator::fillQt2S60LangMapTable() -{ - qt2S60LangMapTable.reserve(170); // 165 items at time of writing. - qt2S60LangMapTable.insert("ab", "SC"); //Abkhazian // - qt2S60LangMapTable.insert("om", "SC"); //Afan // - qt2S60LangMapTable.insert("aa", "SC"); //Afar // - qt2S60LangMapTable.insert("af", "34"); //Afrikaans //Afrikaans - qt2S60LangMapTable.insert("sq", "35"); //Albanian //Albanian - qt2S60LangMapTable.insert("am", "36"); //Amharic //Amharic - qt2S60LangMapTable.insert("ar", "37"); //Arabic //Arabic - qt2S60LangMapTable.insert("hy", "38"); //Armenian //Armenian - qt2S60LangMapTable.insert("as", "SC"); //Assamese // - qt2S60LangMapTable.insert("ay", "SC"); //Aymara // - qt2S60LangMapTable.insert("az", "SC"); //Azerbaijani // - qt2S60LangMapTable.insert("ba", "SC"); //Bashkir // - qt2S60LangMapTable.insert("eu", "SC"); //Basque // - qt2S60LangMapTable.insert("bn", "41"); //Bengali //Bengali - qt2S60LangMapTable.insert("dz", "SC"); //Bhutani // - qt2S60LangMapTable.insert("bh", "SC"); //Bihari // - qt2S60LangMapTable.insert("bi", "SC"); //Bislama // - qt2S60LangMapTable.insert("br", "SC"); //Breton // - qt2S60LangMapTable.insert("bg", "42"); //Bulgarian //Bulgarian - qt2S60LangMapTable.insert("my", "43"); //Burmese //Burmese - qt2S60LangMapTable.insert("be", "40"); //Byelorussian //Belarussian - qt2S60LangMapTable.insert("km", "SC"); //Cambodian // - qt2S60LangMapTable.insert("ca", "44"); //Catalan //Catalan - qt2S60LangMapTable.insert("zh", "SC"); //Chinese // - qt2S60LangMapTable.insert("co", "SC"); //Corsican // - qt2S60LangMapTable.insert("hr", "45"); //Croatian //Croatian - qt2S60LangMapTable.insert("cs", "25"); //Czech //Czech - qt2S60LangMapTable.insert("da", "07"); //Danish //Danish - qt2S60LangMapTable.insert("nl", "18"); //Dutch //Dutch - qt2S60LangMapTable.insert("en", "01"); //English //English(UK) - qt2S60LangMapTable.insert("eo", "SC"); //Esperanto // - qt2S60LangMapTable.insert("et", "49"); //Estonian //Estonian - qt2S60LangMapTable.insert("fo", "SC"); //Faroese // - qt2S60LangMapTable.insert("fj", "SC"); //Fiji // - qt2S60LangMapTable.insert("fi", "09"); //Finnish //Finnish - qt2S60LangMapTable.insert("fr", "02"); //French //French - qt2S60LangMapTable.insert("fy", "SC"); //Frisian // - qt2S60LangMapTable.insert("gd", "52"); //Gaelic //Gaelic - qt2S60LangMapTable.insert("gl", "SC"); //Galician // - qt2S60LangMapTable.insert("ka", "53"); //Georgian //Georgian - qt2S60LangMapTable.insert("de", "03"); //German //German - qt2S60LangMapTable.insert("el", "54"); //Greek //Greek - qt2S60LangMapTable.insert("kl", "SC"); //Greenlandic // - qt2S60LangMapTable.insert("gn", "SC"); //Guarani // - qt2S60LangMapTable.insert("gu", "56"); //Gujarati //Gujarati - qt2S60LangMapTable.insert("ha", "SC"); //Hausa // - qt2S60LangMapTable.insert("he", "57"); //Hebrew //Hebrew - qt2S60LangMapTable.insert("hi", "58"); //Hindi //Hindi - qt2S60LangMapTable.insert("hu", "17"); //Hungarian //Hungarian - qt2S60LangMapTable.insert("is", "15"); //Icelandic //Icelandic - qt2S60LangMapTable.insert("id", "59"); //Indonesian //Indonesian - qt2S60LangMapTable.insert("ia", "SC"); //Interlingua // - qt2S60LangMapTable.insert("ie", "SC"); //Interlingue // - qt2S60LangMapTable.insert("iu", "SC"); //Inuktitut // - qt2S60LangMapTable.insert("ik", "SC"); //Inupiak // - qt2S60LangMapTable.insert("ga", "60"); //Irish //Irish - qt2S60LangMapTable.insert("it", "05"); //Italian //Italian - qt2S60LangMapTable.insert("ja", "32"); //Japanese //Japanese - qt2S60LangMapTable.insert("jv", "SC"); //Javanese // - qt2S60LangMapTable.insert("kn", "62"); //Kannada //Kannada - qt2S60LangMapTable.insert("ks", "SC"); //Kashmiri // - qt2S60LangMapTable.insert("kk", "63"); //Kazakh //Kazakh - qt2S60LangMapTable.insert("rw", "SC"); //Kinyarwanda // - qt2S60LangMapTable.insert("ky", "SC"); //Kirghiz // - qt2S60LangMapTable.insert("ko", "65"); //Korean //Korean - qt2S60LangMapTable.insert("ku", "SC"); //Kurdish // - qt2S60LangMapTable.insert("rn", "SC"); //Kurundi // - qt2S60LangMapTable.insert("lo", "66"); //Laothian //Laothian - qt2S60LangMapTable.insert("la", "SC"); //Latin // - qt2S60LangMapTable.insert("lv", "67"); //Latvian //Latvian - qt2S60LangMapTable.insert("ln", "SC"); //Lingala // - qt2S60LangMapTable.insert("lt", "68"); //Lithuanian //Lithuanian - qt2S60LangMapTable.insert("mk", "69"); //Macedonian //Macedonian - qt2S60LangMapTable.insert("mg", "SC"); //Malagasy // - qt2S60LangMapTable.insert("ms", "70"); //Malay //Malay - qt2S60LangMapTable.insert("ml", "71"); //Malayalam //Malayalam - qt2S60LangMapTable.insert("mt", "SC"); //Maltese // - qt2S60LangMapTable.insert("mi", "SC"); //Maori // - qt2S60LangMapTable.insert("mr", "72"); //Marathi //Marathi - qt2S60LangMapTable.insert("mo", "73"); //Moldavian //Moldovian - qt2S60LangMapTable.insert("mn", "74"); //Mongolian //Mongolian - qt2S60LangMapTable.insert("na", "SC"); //Nauru // - qt2S60LangMapTable.insert("ne", "SC"); //Nepali // - qt2S60LangMapTable.insert("nb", "08"); //Norwegian //Norwegian - qt2S60LangMapTable.insert("oc", "SC"); //Occitan // - qt2S60LangMapTable.insert("or", "SC"); //Oriya // - qt2S60LangMapTable.insert("ps", "SC"); //Pashto // - qt2S60LangMapTable.insert("fa", "SC"); //Persian // - qt2S60LangMapTable.insert("pl", "27"); //Polish //Polish - qt2S60LangMapTable.insert("pt", "13"); //Portuguese //Portuguese - qt2S60LangMapTable.insert("pa", "77"); //Punjabi //Punjabi - qt2S60LangMapTable.insert("qu", "SC"); //Quechua // - qt2S60LangMapTable.insert("rm", "SC"); //RhaetoRomance // - qt2S60LangMapTable.insert("ro", "78"); //Romanian //Romanian - qt2S60LangMapTable.insert("ru", "16"); //Russian //Russian - qt2S60LangMapTable.insert("sm", "SC"); //Samoan // - qt2S60LangMapTable.insert("sg", "SC"); //Sangho // - qt2S60LangMapTable.insert("sa", "SC"); //Sanskrit // - qt2S60LangMapTable.insert("sr", "79"); //Serbian //Serbian - qt2S60LangMapTable.insert("sh", "SC"); //SerboCroatian // - qt2S60LangMapTable.insert("st", "SC"); //Sesotho // - qt2S60LangMapTable.insert("tn", "SC"); //Setswana // - qt2S60LangMapTable.insert("sn", "SC"); //Shona // - qt2S60LangMapTable.insert("sd", "SC"); //Sindhi // - qt2S60LangMapTable.insert("si", "80"); //Singhalese //Sinhalese - qt2S60LangMapTable.insert("ss", "SC"); //Siswati // - qt2S60LangMapTable.insert("sk", "26"); //Slovak //Slovak - qt2S60LangMapTable.insert("sl", "28"); //Slovenian //Slovenian - qt2S60LangMapTable.insert("so", "81"); //Somali //Somali - qt2S60LangMapTable.insert("es", "04"); //Spanish //Spanish - qt2S60LangMapTable.insert("su", "SC"); //Sundanese // - qt2S60LangMapTable.insert("sw", "84"); //Swahili //Swahili - qt2S60LangMapTable.insert("sv", "06"); //Swedish //Swedish - qt2S60LangMapTable.insert("tl", "39"); //Tagalog //Tagalog - qt2S60LangMapTable.insert("tg", "SC"); //Tajik // - qt2S60LangMapTable.insert("ta", "87"); //Tamil //Tamil - qt2S60LangMapTable.insert("tt", "SC"); //Tatar // - qt2S60LangMapTable.insert("te", "88"); //Telugu //Telugu - qt2S60LangMapTable.insert("th", "33"); //Thai //Thai - qt2S60LangMapTable.insert("bo", "89"); //Tibetan //Tibetan - qt2S60LangMapTable.insert("ti", "90"); //Tigrinya //Tigrinya - qt2S60LangMapTable.insert("to", "SC"); //Tonga // - qt2S60LangMapTable.insert("ts", "SC"); //Tsonga // - qt2S60LangMapTable.insert("tr", "14"); //Turkish //Turkish - qt2S60LangMapTable.insert("tk", "92"); //Turkmen //Turkmen - qt2S60LangMapTable.insert("tw", "SC"); //Twi // - qt2S60LangMapTable.insert("ug", "SC"); //Uigur // - qt2S60LangMapTable.insert("uk", "93"); //Ukrainian //Ukrainian - qt2S60LangMapTable.insert("ur", "94"); //Urdu //Urdu - qt2S60LangMapTable.insert("uz", "SC"); //Uzbek // - qt2S60LangMapTable.insert("vi", "96"); //Vietnamese //Vietnamese - qt2S60LangMapTable.insert("vo", "SC"); //Volapuk // - qt2S60LangMapTable.insert("cy", "97"); //Welsh //Welsh - qt2S60LangMapTable.insert("wo", "SC"); //Wolof // - qt2S60LangMapTable.insert("xh", "SC"); //Xhosa // - qt2S60LangMapTable.insert("yi", "SC"); //Yiddish // - qt2S60LangMapTable.insert("yo", "SC"); //Yoruba // - qt2S60LangMapTable.insert("za", "SC"); //Zhuang // - qt2S60LangMapTable.insert("zu", "98"); //Zulu //Zulu - qt2S60LangMapTable.insert("nn", "75"); //Nynorsk //NorwegianNynorsk - qt2S60LangMapTable.insert("bs", "SC"); //Bosnian // - qt2S60LangMapTable.insert("dv", "SC"); //Divehi // - qt2S60LangMapTable.insert("gv", "SC"); //Manx // - qt2S60LangMapTable.insert("kw", "SC"); //Cornish // - qt2S60LangMapTable.insert("ak", "SC"); //Akan // - qt2S60LangMapTable.insert("kok", "SC"); //Konkani // - qt2S60LangMapTable.insert("gaa", "SC"); //Ga // - qt2S60LangMapTable.insert("ig", "SC"); //Igbo // - qt2S60LangMapTable.insert("kam", "SC"); //Kamba // - qt2S60LangMapTable.insert("syr", "SC"); //Syriac // - qt2S60LangMapTable.insert("byn", "SC"); //Blin // - qt2S60LangMapTable.insert("gez", "SC"); //Geez // - qt2S60LangMapTable.insert("kfo", "SC"); //Koro // - qt2S60LangMapTable.insert("sid", "SC"); //Sidamo // - qt2S60LangMapTable.insert("cch", "SC"); //Atsam // - qt2S60LangMapTable.insert("tig", "SC"); //Tigre // - qt2S60LangMapTable.insert("kaj", "SC"); //Jju // - qt2S60LangMapTable.insert("fur", "SC"); //Friulian // - qt2S60LangMapTable.insert("ve", "SC"); //Venda // - qt2S60LangMapTable.insert("ee", "SC"); //Ewe // - qt2S60LangMapTable.insert("wa", "SC"); //Walamo // - qt2S60LangMapTable.insert("haw", "SC"); //Hawaiian // - qt2S60LangMapTable.insert("kcg", "SC"); //Tyap // - qt2S60LangMapTable.insert("ny", "SC"); //Chewa // -} - void SymbianMakefileGenerator::appendIfnotExist(QStringList &list, QString value) { if (!list.contains(value)) @@ -1868,16 +1022,6 @@ void SymbianMakefileGenerator::appendIfnotExist(QStringList &list, QStringList v appendIfnotExist(list, item); } -QString SymbianMakefileGenerator::removePathSeparators(QString &file) -{ - QString ret = file; - while (ret.indexOf(QDir::separator()) > 0) { - ret.remove(0, ret.indexOf(QDir::separator()) + 1); - } - - return ret; -} - QString SymbianMakefileGenerator::removeTrailingPathSeparators(QString &file) { @@ -1903,111 +1047,12 @@ void SymbianMakefileGenerator::generateCleanCommands(QTextStream& t, t << "\t-@ if EXIST \"" << QDir::toNativeSeparators(item) << "\" "; t << cmd << " " << cmdOptions << " \"" << QDir::toNativeSeparators(item) << "\"" << endl; #else - t << "\t-if test -f " << QDir::toNativeSeparators(item) << "; then "; + t << "\t-if test -e " << QDir::toNativeSeparators(item) << "; then "; t << cmd << " " << cmdOptions << " " << QDir::toNativeSeparators(item) << "; fi" << endl; #endif } } -void SymbianMakefileGenerator::removeSpecialCharacters(QString& str) -{ - // When modifying this method check also application_icon.prf - str.replace(QString("/"), QString("_")); - str.replace(QString("\\"), QString("_")); - str.replace(QString("-"), QString("_")); - str.replace(QString(":"), QString("_")); - str.replace(QString("."), QString("_")); - str.replace(QString(" "), QString("_")); -} - -void SymbianMakefileGenerator::writeSisTargets(QTextStream &t) -{ - t << "-include " MAKE_CACHE_NAME << endl; - t << endl; - - t << SIS_TARGET ":" << endl; - QString siscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \ - "$(MAKE) -s -f $(MAKEFILE) %4," \ - "$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \ - "$(MAKE) -s -f $(MAKEFILE) %5))," \ - "$(MAKE) -s -f $(MAKEFILE) %6)") - .arg(fixedTarget) - .arg("pkg") - .arg(MAKE_CACHE_NAME) - .arg(OK_SIS_TARGET) - .arg(FAIL_SIS_NOCACHE_TARGET) - .arg(FAIL_SIS_NOPKG_TARGET); - t << siscommand << endl; - t << endl; - - t << OK_SIS_TARGET ":" << endl; - - QString pkgcommand = QString::fromLatin1("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \ - "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") - .arg(fixedTarget) - .arg("pkg"); - t << pkgcommand << endl; - t << endl; - - QString sisName = fixedTarget; - sisName += ".sis"; - - t << sisName << ":" << endl; - t << "\t$(MAKE) -s -f $(MAKEFILE) " SIS_TARGET << endl << endl; - - t << ROM_STUB_SIS_TARGET ":" << endl; - QString stubsiscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \ - "$(MAKE) -s -f $(MAKEFILE) %4," \ - "$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \ - "$(MAKE) -s -f $(MAKEFILE) %5))," \ - "$(MAKE) -s -f $(MAKEFILE) %6)") - .arg(fixedTarget) - .arg("pkg") - .arg(MAKE_CACHE_NAME) - .arg(OK_ROM_STUB_SIS_TARGET) - .arg(FAIL_SIS_NOCACHE_TARGET) - .arg(FAIL_SIS_NOPKG_TARGET); - t << stubsiscommand << endl; - t << endl; - - t << OK_ROM_STUB_SIS_TARGET ":" << endl; - - QString stubpkgcommand = QString::fromLatin1("\tcreatepackage.bat -s $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \ - "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") - .arg(fixedTarget) - .arg("pkg"); - t << stubpkgcommand << endl; - t << endl; - - t << INSTALLER_SIS_TARGET ": " << sisName << endl; - siscommand = QString::fromLatin1("\t$(if $(wildcard %1_installer.%2)," \ - "$(MAKE) -s -f $(MAKEFILE) %3," \ - "$(MAKE) -s -f $(MAKEFILE) %4)") - .arg(fixedTarget) - .arg("pkg") - .arg(OK_INSTALLER_SIS_TARGET) - .arg(FAIL_SIS_NOPKG_TARGET); - t << siscommand << endl; - t << endl; - - t << OK_INSTALLER_SIS_TARGET ": " << endl; - - pkgcommand = QString::fromLatin1("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_installer.%2 - " \ - "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") - .arg(fixedTarget) - .arg("pkg"); - t << pkgcommand << endl; - t << endl; - - t << FAIL_SIS_NOPKG_TARGET ":" << endl; - t << "\t$(error PKG file does not exist, '" SIS_TARGET "' and '" INSTALLER_SIS_TARGET "' target are only supported for executables or projects with DEPLOYMENT statement)" << endl; - t << endl; - - t << FAIL_SIS_NOCACHE_TARGET ":" << endl; - t << "\t$(error Project has to be built or QT_SIS_TARGET environment variable has to be set before calling 'SIS' target)" << endl; - t << endl; -} - void SymbianMakefileGenerator::generateDistcleanTargets(QTextStream& t) { t << "dodistclean:" << endl; @@ -2062,17 +1107,3 @@ void SymbianMakefileGenerator::generateDistcleanTargets(QTextStream& t) t << "distclean: clean dodistclean" << endl; t << endl; } - -void SymbianMakefileGenerator::generateExecutionTargets(QTextStream& t, const QStringList& platforms) -{ - // create execution targets - if (targetType == TypeExe) { - if (platforms.contains("winscw")) { - t << "run:" << endl; - t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl; - } - t << "runonphone: sis" << endl; - t << "\trunonphone $(QT_RUN_ON_PHONE_OPTIONS) --sis " << fixedTarget << ".sis " << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl; - t << endl; - } -} diff --git a/qmake/generators/symbian/symmake.h b/qmake/generators/symbian/symmake.h index 90c8549450..a1a8e887c1 100644 --- a/qmake/generators/symbian/symmake.h +++ b/qmake/generators/symbian/symmake.h @@ -43,6 +43,7 @@ #define SYMMAKEFILE_H #include "initprojectdeploy_symbian.h" +#include "symbiancommon.h" #include <makefile.h> QT_BEGIN_NAMESPACE @@ -53,22 +54,12 @@ QT_BEGIN_NAMESPACE #define MAKE_CACHE_NAME ".make.cache" #define SYMBIAN_TEST_CONFIG "symbian_test" -class SymbianMakefileGenerator : public MakefileGenerator +class SymbianMakefileGenerator : public MakefileGenerator, public SymbianCommonGenerator { protected: - enum TargetType { - TypeExe, - TypeDll, - TypeLib, - TypePlugin, - TypeSubdirs - }; - QString platform; QString uid2; - QString uid3; - QString privateDirUid; - TargetType targetType; + QString mmpFileName; QMap<QString, QStringList> sources; QMap<QString, QStringList> systeminclude; QMap<QString, QStringList> library; @@ -76,19 +67,10 @@ protected: QMap<QString, QStringList> makmakeCommands; QStringList overriddenMmpKeywords; - QStringList generatedFiles; - QStringList generatedDirs; - QHash<QString, QString> qt2S60LangMapTable; - - QString fixedTarget; - - void removeSpecialCharacters(QString& str); QString fixPathForMmp(const QString& origPath, const QDir& parentDir); QString absolutizePath(const QString& origPath); virtual bool writeMakefile(QTextStream &t); - void generatePkgFile(const QString &iconFile, DeploymentList &depList); - bool containsStartWithItem(const QChar &c, const QStringList& src); virtual void init(); @@ -97,6 +79,7 @@ protected: QString generateUID3(); void initMmpVariables(); + void generateMmpFileName(); void handleMmpRulesOverrides(QString &checkString, bool &inResourceBlock, QStringList &restrictedMmpKeywords, @@ -109,8 +92,7 @@ protected: void writeHeader(QTextStream &t); void writeBldInfContent(QTextStream& t, bool addDeploymentExtension, - const QString &iconFile, - DeploymentList &depList); + const QString &iconFile); static bool removeDuplicatedStrings(QStringList& stringList); @@ -137,25 +119,9 @@ protected: void writeMmpFileBinaryVersionPart(QTextStream& t); void writeMmpFileRulesPart(QTextStream& t); - void writeCustomDefFile(); - - void writeRegRssFile(QMap<QString, QStringList> &useritems); - void writeRegRssList(QTextStream &t, QStringList &userList, - const QString &listTag, - const QString &listItem); - void writeRssFile(QString &numberOfIcons, QString &iconfile); - void writeLocFile(QStringList &symbianLangCodes); - void readRssRules(QString &numberOfIcons, - QString &iconFile, - QMap<QString, QStringList> &userRssRules); - - QStringList symbianLangCodesFromTsFiles(); - void fillQt2S60LangMapTable(); - void appendIfnotExist(QStringList &list, QString value); void appendIfnotExist(QStringList &list, QStringList values); - QString removePathSeparators(QString &file); QString removeTrailingPathSeparators(QString &file); void generateCleanCommands(QTextStream& t, const QStringList& toClean, @@ -164,9 +130,7 @@ protected: const QString& itemPrefix, const QString& itemSuffix); - void writeSisTargets(QTextStream &t); void generateDistcleanTargets(QTextStream& t); - void generateExecutionTargets(QTextStream& t, const QStringList& platforms); // Subclass implements virtual void writeBldInfExtensionRulesPart(QTextStream& t, const QString &iconTargetFile) = 0; diff --git a/qmake/generators/symbian/symmake_abld.cpp b/qmake/generators/symbian/symmake_abld.cpp index ad6e74315c..85dcab4a07 100644 --- a/qmake/generators/symbian/symmake_abld.cpp +++ b/qmake/generators/symbian/symmake_abld.cpp @@ -70,10 +70,6 @@ SymbianAbldMakefileGenerator::~SymbianAbldMakefileGenerator() { } void SymbianAbldMakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly) { - QString gnuMakefileName = QLatin1String("Makefile_") + uid3; - removeSpecialCharacters(gnuMakefileName); - gnuMakefileName.append(".mk"); - QFile ft(gnuMakefileName); if (ft.open(QIODevice::WriteOnly)) { generatedFiles << ft.fileName(); @@ -199,23 +195,28 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool t << "# ==============================================================================" << "\n" << endl; t << endl; - t << "MAKEFILE = " << wrapperFile.fileName() << endl; - t << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl; + t << "MAKEFILE = " << fileInfo(wrapperFile.fileName()).fileName() << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; t << "MOVE = " << var("QMAKE_MOVE") << endl; t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; t << "MKDIR = " << var("QMAKE_MKDIR") << endl; +#ifdef Q_OS_WIN32 t << "XCOPY = xcopy /d /f /h /r /y /i" << endl; t << "ABLD = ABLD.BAT" << endl; +#else + t << "XCOPY = cp -u -v" << endl; + t << "ABLD = abld" << endl; +#endif t << "DEBUG_PLATFORMS = " << debugPlatforms.join(" ") << endl; t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl; t << "MAKE = make" << endl; t << endl; t << "ifeq (WINS,$(findstring WINS, $(PLATFORM)))" << endl; - t << "ZDIR=$(EPOCROOT)epoc32\\release\\$(PLATFORM)\\$(CFG)\\Z" << endl; + t << "ZDIR=$(EPOCROOT)" << QDir::toNativeSeparators("epoc32/release/$(PLATFORM)/$(CFG)/z") << endl; t << "else" << endl; - t << "ZDIR=$(EPOCROOT)epoc32\\data\\z" << endl; + t << "ZDIR=$(EPOCROOT)" << QDir::toNativeSeparators("epoc32/data/z") << endl; t << "endif" << endl; t << endl; t << "DEFINES" << '\t' << " = " @@ -248,13 +249,17 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool } else { t << "all: debug release" << endl; t << endl; + + QString qmakeCmd = "\t$(QMAKE) \"" + project->projectFile() + "\" " + buildArgs(); + t << "qmake:" << endl; - t << "\t$(QMAKE) -spec symbian-abld -o \"" << fileInfo(Option::output.fileName()).fileName() - << "\" \"" << project->projectFile() << "\"" << endl; + t << qmakeCmd << endl; t << endl; - t << BLD_INF_FILENAME ":" << endl; - t << "\t$(QMAKE)" << endl; + + t << BLD_INF_FILENAME ": " << project->projectFile() << endl; + t << qmakeCmd << endl; t << endl; + t << "$(ABLD): " BLD_INF_FILENAME << endl; t << "\tbldmake bldfiles" << endl; t << endl; @@ -309,14 +314,16 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool // generate command lines like this ... // -@ if NOT EXIST ".\somedir" mkdir ".\somedir" QStringList dirsToClean; + QString dirExists = var("QMAKE_CHK_DIR_EXISTS"); + QString mkdir = var("QMAKE_MKDIR"); for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { QStringList values = it.value(); for (int i = 0; i < values.size(); ++i) { if (values.at(i).endsWith("/" QT_EXTRA_INCLUDE_DIR)) { QString fixedValue(QDir::toNativeSeparators(values.at(i))); dirsToClean << fixedValue; - t << "\t-@ if NOT EXIST \"" << fixedValue << "\" mkdir \"" - << fixedValue << "\"" << endl; + t << "\t-@ " << dirExists << " \"" << fixedValue << "\" " + << mkdir << " \"" << fixedValue << "\"" << endl; } } } @@ -325,7 +332,7 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool // Note: EXTENSION_CLEAN will get called many times when doing reallyclean // This is why the "2> NUL" gets appended to generated clean targets in makefile.cpp. t << EXTENSION_CLEAN ": " COMPILER_CLEAN_TARGET << endl; - generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_DIR"), " /S /Q ", "", ""); + generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_TREE"), "", "", ""); t << endl; t << PRE_TARGETDEPS_TARGET ":" @@ -374,10 +381,6 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool writeDeploymentTargets(t, false); writeDeploymentTargets(t, true); - writeSisTargets(t); - - writeStoreBuildTarget(t); - generateDistcleanTargets(t); t << "clean: $(ABLD)" << endl; @@ -406,8 +409,6 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool t << "\t$(ABLD)" << testClause << " reallyclean " << item << " urel" << endl; } t << endl; - - generateExecutionTargets(t, debugPlatforms); } void SymbianAbldMakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t, const QString &iconTargetFile) @@ -429,7 +430,7 @@ bool SymbianAbldMakefileGenerator::writeDeploymentTargets(QTextStream &t, bool i + privateDirUid; DeploymentList depList; - initProjectDeploySymbian(project, depList, remoteTestPath, false, + initProjectDeploySymbian(project, depList, remoteTestPath, false, true, QLatin1String(isRom ? ROM_DEPLOYMENT_PLATFORM : EMULATOR_DEPLOYMENT_PLATFORM), QString(), generatedDirs, generatedFiles); @@ -465,33 +466,13 @@ bool SymbianAbldMakefileGenerator::writeDeploymentTargets(QTextStream &t, bool i return true; } -void SymbianAbldMakefileGenerator::writeStoreBuildTarget(QTextStream &t) -{ - t << STORE_BUILD_TARGET ":" << endl; - t << "\t@echo # ============================================================================== > " MAKE_CACHE_NAME << endl; - t << "\t@echo # This file is generated by make and should not be modified by the user >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # Name : " << MAKE_CACHE_NAME << " >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # Part of : " << project->values("TARGET").join(" ") << " >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # Description : This file is used to cache last build target for >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # make sis target. >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # Version : >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # >> " MAKE_CACHE_NAME << endl; - t << "\t@echo # ============================================================================== >> " MAKE_CACHE_NAME << endl; - t << "\t@echo. >> " MAKE_CACHE_NAME << endl; - t << "\t@echo QT_SIS_TARGET ?= $(QT_SIS_TARGET) >> " MAKE_CACHE_NAME << endl; - t << endl; - - generatedFiles << MAKE_CACHE_NAME; -} - void SymbianAbldMakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) { // Normally emulator deployment gets done via regular makefile, but since subdirs // do not get that, special deployment only makefile is generated for them if needed. if (targetType != TypeSubdirs || addDeploymentExtension) { - QString gnuMakefileName = QLatin1String("Makefile_") + uid3; - removeSpecialCharacters(gnuMakefileName); - gnuMakefileName.append(".mk"); + gnuMakefileName = QLatin1String("Makefile_") + fileInfo(mmpFileName).completeBaseName() + + QLatin1String(".mk"); t << "gnumakefile " << gnuMakefileName << endl; } } diff --git a/qmake/generators/symbian/symmake_abld.h b/qmake/generators/symbian/symmake_abld.h index c03328405a..214e0c5206 100644 --- a/qmake/generators/symbian/symmake_abld.h +++ b/qmake/generators/symbian/symmake_abld.h @@ -57,9 +57,8 @@ protected: virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); - void writeStoreBuildTarget(QTextStream &t); bool writeDeploymentTargets(QTextStream &t, bool isRom); - + QString gnuMakefileName; public: SymbianAbldMakefileGenerator(); diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index 9f3f5c3a58..c66c1b8ca0 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -56,6 +56,12 @@ SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { } #define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt" #define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt" +#define UNDETECTED_GCCE_VERSION "0" +#define PLATFORM_GCCE "gcce" +#define PLATFORM_WINSCW "winscw" +#define PLATFORM_ARMV5 "armv5" +#define BUILD_DEBUG "udeb" +#define BUILD_RELEASE "urel" // Copies Qt FLMs to correct location under epocroot. // This is not done by configure as it is possible to change epocroot after configure. @@ -90,6 +96,67 @@ void SymbianSbsv2MakefileGenerator::exportFlm() } } +QString SymbianSbsv2MakefileGenerator::gcceVersion() +{ + static QString gcceVersionStr; + + if (gcceVersionStr.isEmpty()) { + // First check if QT_GCCE_VERSION has been set, and use that if it is + QByteArray qtGcceVersion = qgetenv("QT_GCCE_VERSION"); + if (!qtGcceVersion.isEmpty()) { + // Check that QT_GCCE_VERSION is in proper format + QString check(qtGcceVersion); + check.replace(QRegExp("^\\d+\\.\\d+\\.\\d+$"),QString()); + if (check.isEmpty()) { + gcceVersionStr = PLATFORM_GCCE + QString(qtGcceVersion).replace(".","_"); + return gcceVersionStr; + } else { + fprintf(stderr, "Warning: Environment variable QT_GCCE_VERSION ('%s') is in incorrect " + "format, expected format is: '1.2.3'. Attempting to autodetect GCCE version.", + qtGcceVersion.constData()); + } + } + // Sbsv2 has separate env variable defined for each gcce version, so try to determine + // which user is likely to want to use by checking version 4.0.0 to 9.9.9 and taking + // the highest found version that actually points to a valid path. + // This is kind of a kludge, but since qmake doesn't bootstrap QProcess, there + // is no Qt API available to get all environment variables. + for (int i = 9; i >= 4; i--) { + for (int j = 9; j >= 0; j--) { + for (int k = 9; k >= 0; k--) { + QByteArray gcceVar = qgetenv(qPrintable(QString("SBS_GCCE%1%2%3BIN").arg(i).arg(j).arg(k))); + if (!gcceVar.isEmpty() && fileInfo(QString::fromLocal8Bit(gcceVar.constData())).exists()) { + gcceVersionStr = QString(PLATFORM_GCCE "%1_%2_%3").arg(i).arg(j).arg(k); + return gcceVersionStr; + } + } + } + } + } + + // Indicate undetected version to avoid rechecking multiple times + if (gcceVersionStr.isEmpty()) + gcceVersionStr = UNDETECTED_GCCE_VERSION; + + return gcceVersionStr; +} + +QString SymbianSbsv2MakefileGenerator::configClause(QString &platform, + QString &build, + QString &winscwClauseTemplate, + QString &gcceClauseTemplate, + QString &genericClauseTemplate) +{ + QString retval; + if (QString::compare(platform, PLATFORM_WINSCW) == 0) + retval = winscwClauseTemplate.arg(build); + else if (QString::compare(platform, PLATFORM_GCCE) == 0) + retval = gcceClauseTemplate.arg(build); + else + retval = genericClauseTemplate.arg(platform).arg(build); + return retval; +} + void SymbianSbsv2MakefileGenerator::writeSbsDeploymentList(const DeploymentList& depList, QTextStream& t) { for (int i = 0; i < depList.size(); ++i) { @@ -99,7 +166,9 @@ void SymbianSbsv2MakefileGenerator::writeSbsDeploymentList(const DeploymentList& fromItem.replace("\\", "/"); toItem.replace("\\", "/"); #if defined(Q_OS_WIN) - toItem.prepend(QDir::current().absolutePath().left(2)); // add drive + // add drive if it doesn't have one yet + if (toItem.size() > 1 && toItem[1] != QLatin1Char(':')) + toItem.prepend(QDir::current().absolutePath().left(2)); #endif t << "OPTION DEPLOY_SOURCE " << fromItem << endl; t << "OPTION DEPLOY_TARGET " << toItem << endl; @@ -116,21 +185,54 @@ void SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile) { + static QString debugBuild(BUILD_DEBUG); + static QString releaseBuild(BUILD_RELEASE); + QStringList allPlatforms; foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) { allPlatforms << platform.toLower(); } - QStringList debugPlatforms = allPlatforms; - QStringList releasePlatforms = allPlatforms; - releasePlatforms.removeAll("winscw"); // No release for emulator - QString testClause; if (project->isActiveConfig(SYMBIAN_TEST_CONFIG)) testClause = QLatin1String(".test"); else testClause = QLatin1String(""); + QString genericClause = " -c %1_%2" + testClause; + QString winscwClause = " -c winscw_%1.mwccinc" + testClause; + QString gcceClause; + bool stripArmv5 = false; + + if (allPlatforms.contains(PLATFORM_GCCE)) { + if (QString::compare(gcceVersion(), UNDETECTED_GCCE_VERSION) == 0) { + allPlatforms.removeAll(PLATFORM_GCCE); + } else { + gcceClause = " -c arm.v5.%1." + gcceVersion() + testClause; + // Since gcce building is enabled, do not add armv5 for any sbs command + // that also contains gcce, because those will build same targets. + stripArmv5 = true; + } + } + + QStringList allClauses; + QStringList debugClauses; + QStringList releaseClauses; + + QStringList debugPlatforms = allPlatforms; + QStringList releasePlatforms = allPlatforms; + releasePlatforms.removeAll(PLATFORM_WINSCW); // No release for emulator + + foreach(QString item, debugPlatforms) { + if (item != PLATFORM_ARMV5 || !stripArmv5) + debugClauses << configClause(item, debugBuild, winscwClause, gcceClause, genericClause); + } + foreach(QString item, releasePlatforms) { + if (item != PLATFORM_ARMV5 || !stripArmv5) + releaseClauses << configClause(item, releaseBuild, winscwClause, gcceClause, genericClause); + } + allClauses << debugClauses << releaseClauses; + QTextStream t(&wrapperFile); t << "# ==============================================================================" << endl; @@ -143,8 +245,8 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo t << "#" << endl; t << "# ==============================================================================" << "\n" << endl; t << endl; - t << "MAKEFILE = " << wrapperFile.fileName() << endl; - t << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl; + t << "MAKEFILE = " << fileInfo(wrapperFile.fileName()).fileName() << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; @@ -170,9 +272,9 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo } t << endl; t << "first: default" << endl; - if (debugPlatforms.contains("winscw")) + if (debugPlatforms.contains(PLATFORM_WINSCW)) t << "default: debug-winscw"; - else if (debugPlatforms.contains("armv5")) + else if (debugPlatforms.contains(PLATFORM_ARMV5)) t << "default: debug-armv5"; else if (debugPlatforms.size()) t << "default: debug-" << debugPlatforms.first(); @@ -185,60 +287,61 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo } else { t << "all: debug release" << endl; t << endl; + + QString qmakeCmd = "\t$(QMAKE) \"" + project->projectFile() + "\" " + buildArgs(); + t << "qmake:" << endl; - t << "\t$(QMAKE) -spec symbian-sbsv2 -o \"" << fileInfo(Option::output.fileName()).fileName() - << "\" \"" << project->projectFile() << "\"" << endl; + t << qmakeCmd << endl; t << endl; - t << BLD_INF_FILENAME ":" << endl; - t << "\t$(QMAKE)" << endl; + + t << BLD_INF_FILENAME ": " << project->projectFile() << endl; + t << qmakeCmd << endl; t << endl; - QString winscw("winscw"); + QString currentClause; + t << "debug: " << BLD_INF_FILENAME << endl; t << "\t$(SBS)"; - foreach(QString item, debugPlatforms) { - if(QString::compare(item, winscw) == 0) - t << " -c " << item << "_udeb.mwccinc" << testClause; - else - t << " -c " << item << "_udeb" << testClause; + foreach(QString item, debugClauses) { + t << item; } t << endl; t << "release: " << BLD_INF_FILENAME << endl; t << "\t$(SBS)"; - foreach(QString item, releasePlatforms) { - if(QString::compare(item, winscw) == 0) - t << " -c " << item << "_urel.mwccinc" << testClause; - else - t << " -c " << item << "_urel" << testClause; + foreach(QString item, releaseClauses) { + t << item; } t << endl; // For more specific builds, targets are in this form: build-platform, e.g. release-armv5 foreach(QString item, debugPlatforms) { t << "debug-" << item << ": " << BLD_INF_FILENAME << endl; - if(QString::compare(item, winscw) == 0) - t << "\t$(SBS) -c " << item << "_udeb.mwccinc" << testClause << endl; - else - t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; + t << "\t$(SBS)"; + t << configClause(item, debugBuild, winscwClause, gcceClause, genericClause); + t << endl; } foreach(QString item, releasePlatforms) { t << "release-" << item << ": " << BLD_INF_FILENAME << endl; - if(QString::compare(item, winscw) == 0) - t << "\t$(SBS) -c " << item << "_urel.mwccinc" << testClause << endl; - else - t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; + t << "\t$(SBS)"; + t << configClause(item, releaseBuild, winscwClause, gcceClause, genericClause); + t << endl; } t << endl; t << "export: " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) export" << endl; - t << endl; + t << "\t$(SBS) export"; + foreach(QString clause, allClauses) { + t << clause; + } + t << endl << endl; t << "cleanexport: " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) cleanexport" << endl; - t << endl; - + t << "\t$(SBS) cleanexport"; + foreach(QString clause, allClauses) { + t << clause; + } + t << endl << endl; } // Add all extra targets including extra compiler targest also to wrapper makefile, @@ -253,39 +356,42 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo qDeleteAll(subtargets); } - writeSisTargets(t); - generateDistcleanTargets(t); t << "clean: " << BLD_INF_FILENAME << endl; - t << "\t-$(SBS) reallyclean" << endl; - t << endl; + t << "\t-$(SBS) reallyclean"; + foreach(QString clause, allClauses) { + t << clause; + } + t << endl << endl; t << "clean-debug: " << BLD_INF_FILENAME << endl; t << "\t$(SBS) reallyclean"; - foreach(QString item, debugPlatforms) { - t << " -c " << item << "_udeb" << testClause; + foreach(QString clause, debugClauses) { + t << clause; } - t << endl; + t << endl << endl; t << "clean-release: " << BLD_INF_FILENAME << endl; t << "\t$(SBS) reallyclean"; - foreach(QString item, releasePlatforms) { - t << " -c " << item << "_urel" << testClause; + foreach(QString clause, releaseClauses) { + t << clause; } - t << endl; + t << endl << endl; // For more specific builds, targets are in this form: clean-build-platform, e.g. clean-release-armv5 foreach(QString item, debugPlatforms) { t << "clean-debug-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) reallyclean -c " << item << "_udeb" << testClause << endl; + t << "\t$(SBS) reallyclean"; + t << configClause(item, debugBuild, winscwClause, gcceClause, genericClause); + t << endl; } foreach(QString item, releasePlatforms) { t << "clean-release-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) reallyclean -c " << item << "_urel" << testClause << endl; + t << "\t$(SBS) reallyclean"; + t << configClause(item, releaseBuild, winscwClause, gcceClause, genericClause); + t << endl; } t << endl; - - generateExecutionTargets(t, debugPlatforms); } void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t, const QString &iconTargetFile) @@ -307,6 +413,28 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t } } + QMap<QString, QString> commandsToReplace; + commandsToReplace.insert(project->values("QMAKE_COPY").join(" "), + project->values("QMAKE_SBSV2_COPY").join(" ")); + commandsToReplace.insert(project->values("QMAKE_COPY_DIR").join(" "), + project->values("QMAKE_SBSV2_COPY_DIR").join(" ")); + commandsToReplace.insert(project->values("QMAKE_MOVE").join(" "), + project->values("QMAKE_SBSV2_MOVE").join(" ")); + commandsToReplace.insert(project->values("QMAKE_DEL_FILE").join(" "), + project->values("QMAKE_SBSV2_DEL_FILE").join(" ")); + commandsToReplace.insert(project->values("QMAKE_MKDIR").join(" "), + project->values("QMAKE_SBSV2_MKDIR").join(" ")); + commandsToReplace.insert(project->values("QMAKE_DEL_DIR").join(" "), + project->values("QMAKE_SBSV2_DEL_DIR").join(" ")); + commandsToReplace.insert(project->values("QMAKE_DEL_TREE").join(" "), + project->values("QMAKE_SBSV2_DEL_TREE").join(" ")); + + // If commandItem starts with any $$QMAKE_* commands, do a replace for SBS equivalent + // Command replacement is done only for the start of the command or right after + // concatenation operators (&& and ||), as otherwise unwanted replacements might occur. + static QString cmdFind("(^|&&\\s*|\\|\\|\\s*)%1"); + static QString cmdReplace("\\1%1"); + // Write extra compilers and targets to initialize QMAKE_ET_* variables // Cache results to avoid duplicate calls when creating wrapper makefile QTextStream extraCompilerStream(&extraCompilersCache); @@ -318,13 +446,7 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t // are not necessary. QStringList allPreDeps; foreach(QString item, project->values("PRE_TARGETDEPS")) { - // Predeps get mangled in windows, so fix them to more sbsv2 friendly format -#if defined(Q_OS_WIN) - if (item.mid(1, 1) == ":") - item = item.mid(0, 1).toUpper().append(item.mid(1)); // Fix drive to uppercase -#endif - item.replace("\\", "/"); - allPreDeps << escapeDependencyPath(item); + allPreDeps.append(fileInfo(item).absoluteFilePath()); } foreach (QString item, project->values("GENERATED_SOURCES")) { @@ -354,7 +476,6 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t QStringList deps = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item + targetItem); QString commandItem = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item + targetItem).join(" "); - // Make sure all deps paths are absolute QString absoluteDeps; foreach (QString depItem, deps) { @@ -368,6 +489,18 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t t << "OPTION PREDEP_TARGET " << absoluteTarget << endl; t << "OPTION DEPS " << absoluteDeps << endl; + // Iterate command replacements in reverse alphabetical order of keys so + // that keys which are starts of other longer keys are iterated after longer keys. + QMapIterator<QString, QString> cmdIter(commandsToReplace); + cmdIter.toBack(); + while (cmdIter.hasPrevious()) { + cmdIter.previous(); + if (commandItem.contains(cmdIter.key())) { + commandItem.replace(QRegExp(cmdFind.arg(cmdIter.key())), + cmdReplace.arg(cmdIter.value())); + } + } + if (commandItem.indexOf("$(INCPATH)") != -1) commandItem.replace("$(INCPATH)", incPath.join(" ")); if (commandItem.indexOf("$(DEFINES)") != -1) @@ -390,7 +523,7 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t //write emulator deployment t << "#if defined(WINSCW)" << endl; - initProjectDeploySymbian(project, depList, remoteTestPath, false, + initProjectDeploySymbian(project, depList, remoteTestPath, false, true, QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM), QString(), generatedDirs, generatedFiles); writeSbsDeploymentList(depList, t); t << "#endif" << endl; @@ -398,7 +531,7 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t //write ROM deployment remoteTestPath = epocRoot() + QLatin1String("epoc32/data/z/private/") + privateDirUid; depList.clear(); - initProjectDeploySymbian(project, depList, remoteTestPath, false, + initProjectDeploySymbian(project, depList, remoteTestPath, false, true, QLatin1String(ROM_DEPLOYMENT_PLATFORM), QString(), generatedDirs, generatedFiles); writeSbsDeploymentList(depList, t); t << endl; diff --git a/qmake/generators/symbian/symmake_sbsv2.h b/qmake/generators/symbian/symmake_sbsv2.h index b8ccdbec98..6644a032c2 100644 --- a/qmake/generators/symbian/symmake_sbsv2.h +++ b/qmake/generators/symbian/symmake_sbsv2.h @@ -56,6 +56,7 @@ protected: virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly); virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); + virtual bool isForSymbianSbsv2() const { return true; } // FIXME: killme - i'm ugly! public: @@ -64,6 +65,13 @@ public: private: void exportFlm(); + QString gcceVersion(); + QString configClause(QString &platform, + QString &build, + QString &winscwClauseTemplate, + QString &gcceClauseTemplate, + QString &genericClauseTemplate); + void writeSbsDeploymentList(const DeploymentList& depList, QTextStream& t); QString extraTargetsCache; diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 670e3a053b..db5b957da9 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -65,6 +65,10 @@ UnixMakefileGenerator::init() } } + if (project->isEmpty("QMAKE_PREFIX_SHLIB")) + // Prevent crash when using the empty variable. + project->values("QMAKE_PREFIX_SHLIB").append(""); + if(!project->isEmpty("QMAKE_FAILED_REQUIREMENTS")) /* no point */ return; @@ -99,8 +103,6 @@ UnixMakefileGenerator::init() MakefileGenerator::init(); if(project->isEmpty("MAKEFILE")) project->values("MAKEFILE").append("Makefile"); - if(project->isEmpty("QMAKE_QMAKE")) - project->values("QMAKE_QMAKE").append("qmake"); if(project->values("QMAKE_INTERNAL_QMAKE_DEPS").indexOf("qmake_all") == -1) project->values("QMAKE_INTERNAL_QMAKE_DEPS").append("qmake_all"); return; /* subdirs is done */ @@ -451,7 +453,9 @@ UnixMakefileGenerator::findLibraries() if(!libdirs.contains(f)) libdirs.append(f); } else if(opt.startsWith("-l")) { - if (project->isActiveConfig("rvct_linker")) { + if (!project->isEmpty("QMAKE_RVCT_LINKSTYLE")) { + (*it) = opt.mid(2); + } else if (project->isActiveConfig("rvct_linker")) { (*it) = "lib" + opt.mid(2) + ".so"; } else { stub = opt.mid(2); @@ -491,26 +495,29 @@ UnixMakefileGenerator::findLibraries() QStringList extens; if(!extn.isNull()) extens << extn; + else if (!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) + // In Symbian you link to the stub .lib file, but run with the .dll file. + extens << "lib"; else extens << project->values("QMAKE_EXTENSION_SHLIB").first() << "a"; for(QStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { if(dir.isNull()) { - QString lib_stub; for(QList<QMakeLocalFileName>::Iterator dep_it = libdirs.begin(); dep_it != libdirs.end(); ++dep_it) { - if(exists((*dep_it).local() + Option::dir_sep + "lib" + stub + - "." + (*extit))) { - lib_stub = stub; + QString pathToLib = ((*dep_it).local() + Option::dir_sep + + project->values("QMAKE_PREFIX_SHLIB").first() + + stub + "." + (*extit)); + if(exists(pathToLib)) { + if (!project->isEmpty("QMAKE_RVCT_LINKSTYLE")) + (*it) = pathToLib; + else + (*it) = "-l" + stub; + found = true; break; } } - if(!lib_stub.isNull()) { - (*it) = "-l" + lib_stub; - found = true; - break; - } } else { - if(exists("lib" + stub + "." + (*extit))) { - (*it) = "lib" + stub + "." + (*extit); + if(exists(project->values("QMAKE_PREFIX_SHLIB").first() + stub + "." + (*extit))) { + (*it) = project->values("QMAKE_PREFIX_SHLIB").first() + stub + "." + (*extit); found = true; break; } @@ -518,8 +525,8 @@ UnixMakefileGenerator::findLibraries() } if(!found && project->isActiveConfig("compile_libtool")) { for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { - if(exists(libdirs[dep_i].local() + Option::dir_sep + "lib" + stub + Option::libtool_ext)) { - (*it) = libdirs[dep_i].real() + Option::dir_sep + "lib" + stub + Option::libtool_ext; + if(exists(libdirs[dep_i].local() + Option::dir_sep + project->values("QMAKE_PREFIX_SHLIB").first() + stub + Option::libtool_ext)) { + (*it) = libdirs[dep_i].real() + Option::dir_sep + project->values("QMAKE_PREFIX_SHLIB").first() + stub + Option::libtool_ext; found = true; break; } @@ -544,7 +551,6 @@ UnixMakefileGenerator::processPrlFiles() { QList<QMakeLocalFileName> libdirs, frameworkdirs; frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks")); - frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks")); const QString lflags[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS", "QMAKE_LFLAGS", "QMAKE_LIBS", QString() }; for(int i = 0; !lflags[i].isNull(); i++) { QStringList &l = project->values(lflags[i]); @@ -560,7 +566,7 @@ UnixMakefileGenerator::processPrlFiles() for(int dep_i = 0; dep_i < libdirs.size(); ++dep_i) { const QMakeLocalFileName &lfn = libdirs[dep_i]; if(!project->isActiveConfig("compile_libtool")) { //give them the .libs.. - QString la = lfn.local() + Option::dir_sep + "lib" + lib + Option::libtool_ext; + QString la = lfn.local() + Option::dir_sep + project->values("QMAKE_PREFIX_SHLIB").first() + lib + Option::libtool_ext; if(exists(la) && QFile::exists(lfn.local() + Option::dir_sep + ".libs")) { QString dot_libs = lfn.real() + Option::dir_sep + ".libs"; l.append("-L" + dot_libs); @@ -568,7 +574,7 @@ UnixMakefileGenerator::processPrlFiles() } } - QString prl = lfn.local() + Option::dir_sep + "lib" + lib; + QString prl = lfn.local() + Option::dir_sep + project->values("QMAKE_PREFIX_SHLIB").first() + lib; if(!project->isEmpty("QMAKE_" + lib.toUpper() + "_SUFFIX")) prl += project->first("QMAKE_" + lib.toUpper() + "_SUFFIX"); if(processPrlFile(prl)) { @@ -779,10 +785,8 @@ UnixMakefileGenerator::defaultInstall(const QString &t) uninst.append("-$(DEL_FILE) \"" + dst_targ + "\""); if(!links.isEmpty()) { for(int i = 0; i < links.size(); ++i) { - if(Option::target_mode == Option::TARG_WIN_MODE || - Option::target_mode == Option::TARG_MAC9_MODE) { - } else if(Option::target_mode == Option::TARG_UNIX_MODE || - Option::target_mode == Option::TARG_MACX_MODE) { + if(Option::target_mode == Option::TARG_UNIX_MODE || + Option::target_mode == Option::TARG_MACX_MODE) { QString link = Option::fixPathToTargetOS(destdir + links[i], false); int lslash = link.lastIndexOf(Option::dir_sep); if(lslash != -1) diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index 77bdd01978..0ea33506c7 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE class UnixMakefileGenerator : public MakefileGenerator { bool init_flag, include_deps; - bool writeMakefile(QTextStream &); QString libtoolFileName(bool fixify=true); void writeLibtoolFile(); // for libtool QString pkgConfigPrefix() const; @@ -75,6 +74,7 @@ protected: virtual void init(); void writeMakeParts(QTextStream &); + bool writeMakefile(QTextStream &); private: void init2(); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 025882e942..d16cd6b317 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -81,7 +81,7 @@ UnixMakefileGenerator::writeMakefile(QTextStream &t) writeHeader(t); if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; QStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; @@ -148,13 +148,13 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isActiveConfig("staticlib")) { t << "LINK = " << var("QMAKE_LINK") << endl; t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; - t << "LIBS = " << "$(SUBLIBS) " << var("QMAKE_FRAMEWORKDIR_FLAGS") << " " + t << "LIBS = " << "$(SUBLIBS) " << var("QMAKE_FRAMEWORKPATH_FLAGS") << " " << var("QMAKE_LIBDIR_FLAGS") << " " << var("QMAKE_LIBS") << " " << var("QMAKE_LIBS_PRIVATE") << endl; } t << "AR = " << var("QMAKE_AR") << endl; t << "RANLIB = " << var("QMAKE_RANLIB") << endl; - t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "TAR = " << var("QMAKE_TAR") << endl; t << "COMPRESS = " << var("QMAKE_GZIP") << endl; if(project->isActiveConfig("compile_libtool")) @@ -177,6 +177,12 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isEmpty("QMAKE_MACOSX_DEPLOYMENT_TARGET")) t << "export MACOSX_DEPLOYMENT_TARGET = " //exported to children processes << project->first("QMAKE_MACOSX_DEPLOYMENT_TARGET") << endl; + + if (!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) { + t << "vpath %.dso " << project->values("QMAKE_LIBDIR").join(":") << endl; + t << "vpath %.lib " << project->values("QMAKE_LIBDIR").join(":") << endl; + } + t << endl; t << "####### Output directory" << endl << endl; @@ -233,6 +239,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isEmpty("QMAKE_BUNDLE")) { t << "TARGETD = " << escapeFilePath(var("TARGET_x.y")) << endl; t << "TARGET0 = " << escapeFilePath(var("TARGET_")) << endl; + } else if(!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) { + t << "TARGETD = " << escapeFilePath(var("TARGET")) << endl; } else if(project->isEmpty("QMAKE_HPUX_SHLIB")) { t << "TARGETD = " << escapeFilePath(var("TARGET_x.y.z")) << endl; t << "TARGET0 = " << escapeFilePath(var("TARGET_")) << endl; @@ -332,7 +340,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "SUBLIBS = "; QStringList &l = project->values("SUBLIBS"); for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) - t << libdir << "lib" << (*it) << ".a "; + t << libdir << project->first("QMAKE_PREFIX_STATICLIB") << (*it) << "." + << project->first("QMAKE_EXTENSION_STATICLIB") << " "; t << endl << endl; } if(project->isActiveConfig("depend_prl") && !project->isEmpty("QMAKE_PRL_INTERNAL_FILES")) { @@ -545,6 +554,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; + } else if(!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) { + t << "\n\t" + << "-$(DEL_FILE) $(TARGET)" << "\n\t" + << var("QMAKE_LINK_SHLIB_CMD"); + if(!destdir.isEmpty()) + t << "\n\t" + << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t" + << "-$(MOVE) $(TARGET) " << destdir; + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK"); + t << endl << endl; } else if(project->isEmpty("QMAKE_HPUX_SHLIB")) { t << "\n\t" << "-$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2)" << "\n\t" @@ -860,7 +880,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) libdir = project->first("SUBLIBS_DIR"); QStringList &l = project->values("SUBLIBS"); for(it = l.begin(); it != l.end(); ++it) - t << libdir << "lib" << (*it) << ".a" << ":\n\t" + t << libdir << project->first("QMAKE_PREFIX_STATICLIB") << (*it) << "." + << project->first("QMAKE_EXTENSION_STATICLIB") << ":\n\t" << var(QString("MAKELIB") + (*it)) << endl << endl; } @@ -875,9 +896,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "\t-$(LIBTOOL) --mode=clean $(DEL_FILE) " << "$(TARGET)" << endl; } else if(!project->isActiveConfig("staticlib") && project->values("QMAKE_APP_FLAG").isEmpty() && !project->isActiveConfig("plugin")) { - t << "\t-$(DEL_FILE) " << destdir << "$(TARGET)" << " " << endl - << "\t-$(DEL_FILE) " << destdir << "$(TARGET0) " << destdir << "$(TARGET1) " - << destdir << "$(TARGET2) $(TARGETA)" << endl; + t << "\t-$(DEL_FILE) " << destdir << "$(TARGET)" << " " << endl; + if (project->values("QMAKE_SYMBIAN_SHLIB").isEmpty()) + t << "\t-$(DEL_FILE) " << destdir << "$(TARGET0) " << destdir << "$(TARGET1) " + << destdir << "$(TARGET2) $(TARGETA)" << endl; } else { t << "\t-$(DEL_FILE) " << "$(TARGET)" << " " << endl; } @@ -992,12 +1014,13 @@ void UnixMakefileGenerator::init2() if (!project->values("QMAKE_CYGWIN_EXE").isEmpty()) project->values("TARGET_EXT").append(".exe"); } else if (project->isActiveConfig("staticlib")) { - project->values("TARGET").first().prepend("lib"); - project->values("TARGET").first() += ".a"; + project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB")); + project->values("TARGET").first() += "." + project->first("QMAKE_EXTENSION_STATICLIB"); if(project->values("QMAKE_AR_CMD").isEmpty()) project->values("QMAKE_AR_CMD").append("$(AR) $(TARGET) $(OBJECTS)"); } else { - project->values("TARGETA").append(project->first("DESTDIR") + "lib" + project->first("TARGET") + ".a"); + project->values("TARGETA").append(project->first("DESTDIR") + project->first("QMAKE_PREFIX_STATICLIB") + + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_STATICLIB")); if(project->isActiveConfig("compile_libtool")) project->values("TARGET_la") = QStringList(project->first("DESTDIR") + "lib" + project->first("TARGET") + Option::libtool_ext); @@ -1045,7 +1068,8 @@ void UnixMakefileGenerator::init2() project->first("VER_MAJ")); project->values("TARGET") = project->values("TARGET_x"); } else if (!project->isEmpty("QMAKE_AIX_SHLIB")) { - project->values("TARGET_").append("lib" + project->first("TARGET") + ".a"); + project->values("TARGET_").append(project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET") + + "." + project->first("QMAKE_EXTENSION_STATICLIB")); if(project->isActiveConfig("lib_version_first")) { project->values("TARGET_x").append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + @@ -1074,6 +1098,10 @@ void UnixMakefileGenerator::init2() project->first("VER_PAT")); } project->values("TARGET") = project->values("TARGET_x.y.z"); + } else if (!project->isEmpty("QMAKE_SYMBIAN_SHLIB")) { + project->values("TARGET_").append(project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + project->values("TARGET") = project->values("TARGET_"); } else { project->values("TARGET_").append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB")); diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp index 9208e1d2b6..b5c33c432c 100644 --- a/qmake/generators/win32/borland_bmake.cpp +++ b/qmake/generators/win32/borland_bmake.cpp @@ -115,8 +115,6 @@ BorlandMakefileGenerator::init() project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); - if(project->values("QMAKE_QMAKE").isEmpty()) - project->values("QMAKE_QMAKE").append("qmake"); return; } diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index e1f502f68e..4717542892 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -143,7 +143,7 @@ bool MingwMakefileGenerator::writeMakefile(QTextStream &t) if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { if(Option::mkfile::do_stub_makefile) { - t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; QStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; @@ -191,10 +191,7 @@ void createArObjectScriptFile(const QString &fileName, const QString &target, co QTextStream t(&file); t << "CREATE " << target << endl; for (QStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) { - if (QDir::isRelativePath(*it)) - t << "ADDMOD " << *it << endl; - else - t << *it << endl; + t << "ADDMOD " << *it << endl; } t << "SAVE" << endl; t.flush(); @@ -248,8 +245,6 @@ void MingwMakefileGenerator::init() project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); - if(project->values("QMAKE_QMAKE").isEmpty()) - project->values("QMAKE_QMAKE").append("qmake"); return; } @@ -373,7 +368,12 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t) ar_script_file += "." + var("BUILD_NAME"); } createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS")); - objectsLinkLine = "ar -M < " + ar_script_file; + // QMAKE_LIB is used for win32, including mingw, whereas QMAKE_AR is used on Unix. + // Strip off any options since the ar commands will be read from file. + QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0);; + if (ar_cmd.isEmpty()) + ar_cmd = "ar"; + objectsLinkLine = ar_cmd + " -M < " + ar_script_file; } else { QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); if (!var("BUILD_NAME").isEmpty()) { @@ -417,7 +417,7 @@ void MingwMakefileGenerator::writeRcFilePart(QTextStream &t) if (!rc_file.isEmpty()) { t << escapeDependencyPath(var("RES_FILE")) << ": " << rc_file << "\n\t" << var("QMAKE_RC") << " -i " << rc_file << " -o " << var("RES_FILE") - << " --include-dir=" << incPathStr << endl << endl; + << " --include-dir=" << incPathStr << " $(DEFINES)" << endl << endl; } } diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp new file mode 100644 index 0000000000..2505056e73 --- /dev/null +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -0,0 +1,3379 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "msvc_objectmodel.h" +#include "msbuild_objectmodel.h" +#include "msvc_vcproj.h" +#include "msvc_vcxproj.h" +#include <qstringlist.h> +#include <qfileinfo.h> + +QT_BEGIN_NAMESPACE + +// XML Tags --------------------------------------------------------- +const char _CLCompile[] = "ClCompile"; +const char _Configuration[] = "Configuration"; +const char _Configurations[] = "Configurations"; +const char q_File[] = "File"; +const char _FileConfiguration[] = "FileConfiguration"; +const char q_Files[] = "Files"; +const char _Filter[] = "Filter"; +const char _Globals[] = "Globals"; +const char _ItemGroup[] = "ItemGroup"; +const char _Link[] = "Link"; +const char _Midl[] = "Midl"; +const char _Platform[] = "Platform"; +const char _Platforms[] = "Platforms"; +const char _ResourceCompile[] = "ResourceCompile"; +const char _Tool[] = "Tool"; +const char _VisualStudioProject[] = "VisualStudioProject"; + +// XML Properties --------------------------------------------------- +const char _AddModuleNamesToAssembly[] = "AddModuleNamesToAssembly"; +const char _AdditionalDependencies[] = "AdditionalDependencies"; +const char _AdditionalFiles[] = "AdditionalFiles"; +const char _AdditionalIncludeDirectories[] = "AdditionalIncludeDirectories"; +const char _AdditionalLibraryDirectories[] = "AdditionalLibraryDirectories"; +const char _AdditionalManifestDependencies[] = "AdditionalManifestDependencies"; +const char _AdditionalOptions[] = "AdditionalOptions"; +const char _AdditionalUsingDirectories[] = "AdditionalUsingDirectories"; +const char _AllowIsolation[] = "AllowIsolation"; +const char _AlwaysAppend[] = "AlwaysAppend"; +const char _ApplicationConfigurationMode[] = "ApplicationConfigurationMode"; +const char _AssemblerListingLocation[] = "AssemblerListingLocation"; +const char _AssemblerOutput[] = "AssemblerOutput"; +const char _AssemblyDebug[] = "AssemblyDebug"; +const char _AssemblyLinkResource[] = "AssemblyLinkResource"; +const char _ATLMinimizesCRunTimeLibraryUsage[] = "ATLMinimizesCRunTimeLibraryUsage"; +const char _BaseAddress[] = "BaseAddress"; +const char _BasicRuntimeChecks[] = "BasicRuntimeChecks"; +const char _BrowseInformation[] = "BrowseInformation"; +const char _BrowseInformationFile[] = "BrowseInformationFile"; +const char _BufferSecurityCheck[] = "BufferSecurityCheck"; +const char _BuildBrowserInformation[] = "BuildBrowserInformation"; +const char _CallingConvention[] = "CallingConvention"; +const char _CharacterSet[] = "CharacterSet"; +const char _ClientStubFile[] = "ClientStubFile"; +const char _CLRImageType[] = "CLRImageType"; +const char _CLRSupportLastError[] = "CLRSupportLastError"; +const char _CLRThreadAttribute[] = "CLRThreadAttribute"; +const char _CLRUnmanagedCodeCheck[] = "CLRUnmanagedCodeCheck"; +const char _Command[] = "Command"; +const char _CommandLine[] = "CommandLine"; +const char _CompileAs[] = "CompileAs"; +const char _CompileAsManaged[] = "CompileAsManaged"; +const char _CompileForArchitecture[] = "CompileForArchitecture"; +const char _CompileOnly[] = "CompileOnly"; +const char _ConfigurationType[] = "ConfigurationType"; +const char _CPreprocessOptions[] = "CPreprocessOptions"; +const char _CreateHotpatchableImage[] = "CreateHotpatchableImage"; +const char _CreateHotPatchableImage[] = "CreateHotPatchableImage"; +const char _Culture[] = "Culture"; +const char _DataExecutionPrevention[] = "DataExecutionPrevention"; +const char _DebugInformationFormat[] = "DebugInformationFormat"; +const char _DefaultCharIsUnsigned[] = "DefaultCharIsUnsigned"; +const char _DefaultCharType[] = "DefaultCharType"; +const char _DelayLoadDLLs[] = "DelayLoadDLLs"; +const char _DelaySign[] = "DelaySign"; +const char _DeleteExtensionsOnClean[] = "DeleteExtensionsOnClean"; +const char _Description[] = "Description"; +const char _Detect64BitPortabilityProblems[] = "Detect64BitPortabilityProblems"; +const char _DisableLanguageExtensions[] = "DisableLanguageExtensions"; +const char _DisableSpecificWarnings[] = "DisableSpecificWarnings"; +const char _DisplayLibrary[] = "DisplayLibrary"; +const char _DLLDataFileName[] = "DLLDataFileName"; +const char _Driver[] = "Driver"; +const char _EmbedManagedResourceFile[] = "EmbedManagedResourceFile"; +const char _EnableCOMDATFolding[] = "EnableCOMDATFolding"; +const char _EnableUAC[] = "EnableUAC"; +const char _EnableErrorChecks[] = "EnableErrorChecks"; +const char _EnableEnhancedInstructionSet[] = "EnableEnhancedInstructionSet"; +const char _EnableFiberSafeOptimizations[] = "EnableFiberSafeOptimizations"; +const char _EnableFunctionLevelLinking[] = "EnableFunctionLevelLinking"; +const char _EnableIntrinsicFunctions[] = "EnableIntrinsicFunctions"; +const char _EnablePREfast[] = "EnablePREfast"; +const char _EntryPointSymbol[] = "EntryPointSymbol"; +const char _ErrorCheckAllocations[] = "ErrorCheckAllocations"; +const char _ErrorCheckBounds[] = "ErrorCheckBounds"; +const char _ErrorCheckEnumRange[] = "ErrorCheckEnumRange"; +const char _ErrorCheckRefPointers[] = "ErrorCheckRefPointers"; +const char _ErrorCheckStubData[] = "ErrorCheckStubData"; +const char _ErrorReporting[] = "ErrorReporting"; +const char _ExceptionHandling[] = "ExceptionHandling"; +const char _ExcludedFromBuild[] = "ExcludedFromBuild"; +const char _ExpandAttributedSource[] = "ExpandAttributedSource"; +const char _ExportNamedFunctions[] = "ExportNamedFunctions"; +const char _FavorSizeOrSpeed[] = "FavorSizeOrSpeed"; +const char _FixedBaseAddress[] = "FixedBaseAddress"; +const char _FloatingPointModel[] = "FloatingPointModel"; +const char _FloatingPointExceptions[] = "FloatingPointExceptions"; +const char _ForceConformanceInForLoopScope[] = "ForceConformanceInForLoopScope"; +const char _ForceFileOutput[] = "ForceFileOutput"; +const char _ForceSymbolReferences[] = "ForceSymbolReferences"; +const char _ForcedIncludeFiles[] = "ForcedIncludeFiles"; +const char _ForcedUsingFiles[] = "ForcedUsingFiles"; +const char _FullIncludePath[] = "FullIncludePath"; +const char _FunctionLevelLinking[] = "FunctionLevelLinking"; +const char _FunctionOrder[] = "FunctionOrder"; +const char _GenerateClientFiles[] = "GenerateClientFiles"; +const char _GenerateDebugInformation[] = "GenerateDebugInformation"; +const char _GenerateManifest[] = "GenerateManifest"; +const char _GenerateMapFile[] = "GenerateMapFile"; +const char _GeneratePreprocessedFile[] = "GeneratePreprocessedFile"; +const char _GenerateServerFiles[] = "GenerateServerFiles"; +const char _GenerateStublessProxies[] = "GenerateStublessProxies"; +const char _GenerateTypeLibrary[] = "GenerateTypeLibrary"; +const char _GenerateXMLDocumentationFiles[] = "GenerateXMLDocumentationFiles"; +const char _GlobalOptimizations[] = "GlobalOptimizations"; +const char _HeaderFileName[] = "HeaderFileName"; +const char _HeapCommitSize[] = "HeapCommitSize"; +const char _HeapReserveSize[] = "HeapReserveSize"; +const char _IgnoreAllDefaultLibraries[] = "IgnoreAllDefaultLibraries"; +const char _IgnoreDefaultLibraryNames[] = "IgnoreDefaultLibraryNames"; +const char _IgnoreEmbeddedIDL[] = "IgnoreEmbeddedIDL"; +const char _IgnoreImportLibrary[] = "IgnoreImportLibrary"; +const char _IgnoreSpecificDefaultLibraries[] = "IgnoreSpecificDefaultLibraries"; +const char _IgnoreStandardIncludePath[] = "IgnoreStandardIncludePath"; +const char _ImageHasSafeExceptionHandlers[] = "ImageHasSafeExceptionHandlers"; +const char _ImportLibrary[] = "ImportLibrary"; +const char _ImproveFloatingPointConsistency[] = "ImproveFloatingPointConsistency"; +const char _InlineFunctionExpansion[] = "InlineFunctionExpansion"; +const char _IntrinsicFunctions[] = "IntrinsicFunctions"; +const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName"; +const char _IntermediateDirectory[] = "IntermediateDirectory"; +const char _InterworkCalls[] = "InterworkCalls"; +const char _KeyContainer[] = "KeyContainer"; +const char _KeyFile[] = "KeyFile"; +const char _Keyword[] = "Keyword"; +const char _KeepComments[] = "KeepComments"; +const char _LargeAddressAware[] = "LargeAddressAware"; +const char _LinkDLL[] = "LinkDLL"; +const char _LinkErrorReporting[] = "LinkErrorReporting"; +const char _LinkIncremental[] = "LinkIncremental"; +const char _LinkStatus[] = "LinkStatus"; +const char _LinkTimeCodeGeneration[] = "LinkTimeCodeGeneration"; +const char _LinkToManagedResourceFile[] = "LinkToManagedResourceFile"; +const char _LocaleID[] = "LocaleID"; +const char _ManifestFile[] = "ManifestFile"; +const char _MapExports[] = "MapExports"; +const char _MapFileName[] = "MapFileName"; +const char _MapLines[] = "MapLines "; +const char _MergedIDLBaseFileName[] = "MergedIDLBaseFileName"; +const char _MergeSections[] = "MergeSections"; +const char _Message[] = "Message"; +const char _MidlCommandFile[] = "MidlCommandFile"; +const char _MinimalRebuild[] = "MinimalRebuild"; +const char _MkTypLibCompatible[] = "MkTypLibCompatible"; +const char _ModuleDefinitionFile[] = "ModuleDefinitionFile"; +const char _MSDOSStubFileName[] = "MSDOSStubFileName"; +const char _MultiProcessorCompilation[] = "MultiProcessorCompilation"; +const char _Name[] = "Name"; +const char _NoEntryPoint[] = "NoEntryPoint"; +const char _NullTerminateStrings[] = "NullTerminateStrings"; +const char _ObjectFile[] = "ObjectFile"; +const char _ObjectFiles[] = "ObjectFiles"; +const char _ObjectFileName[] = "ObjectFileName"; +const char _OmitDefaultLibName[] = "OmitDefaultLibName"; +const char _OmitFramePointers[] = "OmitFramePointers"; +const char _OpenMP[] = "OpenMP"; +const char _OpenMPSupport[] = "OpenMPSupport"; +const char _Optimization[] = "Optimization"; +const char _OptimizeForProcessor[] = "OptimizeForProcessor"; +const char _OptimizeForWindows98[] = "OptimizeForWindows98"; +const char _OptimizeForWindowsApplication[] = "OptimizeForWindowsApplication"; +const char _OptimizeReferences[] = "OptimizeReferences"; +const char _OutputDirectory[] = "OutputDirectory"; +const char _OutputFile[] = "OutputFile"; +const char _Outputs[] = "Outputs"; +const char _ParseFiles[] = "ParseFiles"; +const char _Path[] = "Path"; +const char _PrecompiledHeader[] = "PrecompiledHeader"; +const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile"; +const char _PrecompiledHeaderOutputFile[] = "PrecompiledHeaderOutputFile"; +const char _PrecompiledHeaderThrough[] = "PrecompiledHeaderThrough"; +const char _PreprocessorDefinitions[] = "PreprocessorDefinitions"; +const char _PreprocessKeepComments[] = "PreprocessKeepComments"; +const char _PreprocessOutputPath[] = "PreprocessOutputPath"; +const char _PreprocessSuppressLineNumbers[] = "PreprocessSuppressLineNumbers"; +const char _PreprocessToFile[] = "PreprocessToFile"; +const char _PreventDllBinding[] = "PreventDllBinding"; +const char _PrimaryOutput[] = "PrimaryOutput"; +const char _Profile[] = "Profile"; +const char _ProfileGuidedDatabase[] = "ProfileGuidedDatabase"; +const char _ProjectGUID[] = "ProjectGUID"; +const char _ProcessorNumber[] = "ProcessorNumber"; +const char _ProjectType[] = "ProjectType"; +const char _ProgramDatabase[] = "ProgramDatabase"; +const char _ProgramDataBaseFileName[] = "ProgramDataBaseFileName"; +const char _ProgramDatabaseFile[] = "ProgramDatabaseFile"; +const char _ProxyFileName[] = "ProxyFileName"; +const char _RandomizedBaseAddress[] = "RandomizedBaseAddress"; +const char _RedirectOutputAndErrors[] = "RedirectOutputAndErrors"; +const char _RegisterOutput[] = "RegisterOutput"; +const char _RelativePath[] = "RelativePath"; +const char _RemoteDirectory[] = "RemoteDirectory"; +const char _RemoveObjects[] = "RemoveObjects"; +const char _ResourceOnlyDLL[] = "ResourceOnlyDLL"; +const char _ResourceOutputFileName[] = "ResourceOutputFileName"; +const char _RuntimeLibrary[] = "RuntimeLibrary"; +const char _RuntimeTypeInfo[] = "RuntimeTypeInfo"; +const char _SccProjectName[] = "SccProjectName"; +const char _SccLocalPath[] = "SccLocalPath"; +const char _SectionAlignment[] = "SectionAlignment"; +const char _ServerStubFile[] = "ServerStubFile"; +const char _SetChecksum[] = "SetChecksum"; +const char _ShowIncludes[] = "ShowIncludes"; +const char _ShowProgress[] = "ShowProgress"; +const char _SmallerTypeCheck[] = "SmallerTypeCheck"; +const char _SpecifySectionAttributes[] = "SpecifySectionAttributes"; +const char _StackCommitSize[] = "StackCommitSize"; +const char _StackReserveSize[] = "StackReserveSize"; +const char _StringPooling[] = "StringPooling"; +const char _StripPrivateSymbols[] = "StripPrivateSymbols"; +const char _StructMemberAlignment[] = "StructMemberAlignment"; +const char _SubSystem[] = "SubSystem"; +const char _SupportNobindOfDelayLoadedDLL[] = "SupportNobindOfDelayLoadedDLL"; +const char _SupportUnloadOfDelayLoadedDLL[] = "SupportUnloadOfDelayLoadedDLL"; +const char _SuppressCompilerWarnings[] = "SuppressCompilerWarnings"; +const char _SuppressStartupBanner[] = "SuppressStartupBanner"; +const char _SwapRunFromCD[] = "SwapRunFromCD"; +const char _SwapRunFromNet[] = "SwapRunFromNet"; +const char _TargetEnvironment[] = "TargetEnvironment"; +const char _TargetMachine[] = "TargetMachine"; +const char _TerminalServerAware[] = "TerminalServerAware"; +const char _TrackerLogDirectory[] = "TrackerLogDirectory"; +const char _TreatLibWarningAsErrors[] = "TreatLibWarningAsErrors"; +const char _TreatLinkerWarningAsErrors[] = "TreatLinkerWarningAsErrors"; +const char _TreatSpecificWarningsAsErrors[] = "TreatSpecificWarningsAsErrors"; +const char _TreatWarningAsError[] = "TreatWarningAsError"; +const char _TreatWChar_tAsBuiltInType[] = "TreatWChar_tAsBuiltInType"; +const char _TurnOffAssemblyGeneration[] = "TurnOffAssemblyGeneration"; +const char _TypeLibFormat[] = "TypeLibFormat"; +const char _TypeLibraryFile[] = "TypeLibraryFile"; +const char _TypeLibraryName[] = "TypeLibraryName"; +const char _TypeLibraryResourceID[] = "TypeLibraryResourceID"; +const char _UACExecutionLevel[] = "UACExecutionLevel"; +const char _UACUIAccess[] = "UACUIAccess"; +const char _UndefineAllPreprocessorDefinitions[]= "UndefineAllPreprocessorDefinitions"; +const char _UndefinePreprocessorDefinitions[] = "UndefinePreprocessorDefinitions"; +const char _UniqueIdentifier[] = "UniqueIdentifier"; +const char _UseFullPaths[] = "UseFullPaths"; +const char _UseOfATL[] = "UseOfATL"; +const char _UseOfMfc[] = "UseOfMfc"; +const char _UsePrecompiledHeader[] = "UsePrecompiledHeader"; +const char _UseUnicodeForAssemblerListing[] = "UseUnicodeForAssemblerListing"; +const char _ValidateAllParameters[] = "ValidateAllParameters"; +const char _VCCLCompilerTool[] = "VCCLCompilerTool"; +const char _VCLibrarianTool[] = "VCLibrarianTool"; +const char _VCLinkerTool[] = "VCLinkerTool"; +const char _VCCustomBuildTool[] = "VCCustomBuildTool"; +const char _VCResourceCompilerTool[] = "VCResourceCompilerTool"; +const char _VCMIDLTool[] = "VCMIDLTool"; +const char _Verbose[] = "Verbose"; +const char _Version[] = "Version"; +const char _WarnAsError[] = "WarnAsError"; +const char _WarningLevel[] = "WarningLevel"; +const char _WholeProgramOptimization[] = "WholeProgramOptimization"; +const char _XMLDocumentationFileName[] = "XMLDocumentationFileName"; + + +// XmlOutput stream functions ------------------------------ +inline XmlOutput::xml_output attrTagT(const char *name, const triState v) +{ + if(v == unset) + return noxml(); + return tagValue(name, (v == _True ? "true" : "false")); +} + +inline XmlOutput::xml_output attrTagL(const char *name, qint64 v) +{ + return tagValue(name, QString::number(v)); +} + +/*ifNot version*/ +inline XmlOutput::xml_output attrTagL(const char *name, qint64 v, qint64 ifn) +{ + if (v == ifn) + return noxml(); + return tagValue(name, QString::number(v)); +} + +inline XmlOutput::xml_output attrTagS(const char *name, const QString &v) +{ + if(v.isEmpty()) + return noxml(); + return tagValue(name, v); +} + + +inline XmlOutput::xml_output attrTagX(const char *name, const QStringList &v, const char *s = ",") +{ + if(v.isEmpty()) + return noxml(); + QStringList temp = v; + temp.append(QString("%(%1)").arg(name)); + return tagValue(name, temp.join(s)); +} + +inline XmlOutput::xml_output valueTagX(const QStringList &v, const char *s = " ") +{ + if(v.isEmpty()) + return noxml(); + return valueTag(v.join(s)); +} + +inline XmlOutput::xml_output valueTagDefX(const QStringList &v, const QString &tagName, const char *s = " ") +{ + if(v.isEmpty()) + return noxml(); + QStringList temp = v; + temp.append(QString("%(%1)").arg(tagName)); + return valueTag(temp.join(s)); +} + +inline XmlOutput::xml_output valueTagT( const triState v) +{ + if(v == unset) + return noxml(); + return valueTag(v == _True ? "true" : "false"); +} + + +// VCXCLCompilerTool ------------------------------------------------- +VCXCLCompilerTool::VCXCLCompilerTool() + : BrowseInformation(_False), + BufferSecurityCheck(_False), + CreateHotpatchableImage(unset), + DisableLanguageExtensions(unset), + EnableFiberSafeOptimizations(unset), + EnablePREfast(unset), + ExpandAttributedSource(unset), + FloatingPointExceptions(unset), + ForceConformanceInForLoopScope(unset), + FunctionLevelLinking(unset), + GenerateXMLDocumentationFiles(unset), + IgnoreStandardIncludePath(unset), + IntrinsicFunctions(unset), + MinimalRebuild(unset), + MultiProcessorCompilation(unset), + OmitDefaultLibName(unset), + OmitFramePointers(unset), + Optimization("Disabled"), + OpenMPSupport(unset), + PreprocessKeepComments(unset), + PreprocessSuppressLineNumbers(unset), + RuntimeTypeInfo(unset), + ShowIncludes(unset), + SmallerTypeCheck(unset), + StringPooling(unset), + SuppressStartupBanner(unset), + TreatWarningAsError(unset), + TreatWChar_tAsBuiltInType(unset), + UndefineAllPreprocessorDefinitions(unset), + UseFullPaths(unset), + UseUnicodeForAssemblerListing(unset), + WholeProgramOptimization(unset) +{ +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXCLCompilerTool &tool) +{ + return xml + << tag(_CLCompile) + << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrTagX(_AdditionalUsingDirectories, tool.AdditionalUsingDirectories, ";") + << attrTagS(_AlwaysAppend, tool.AlwaysAppend) + << attrTagS(_AssemblerListingLocation, tool.AssemblerListingLocation) + << attrTagS(_AssemblerOutput, tool.AssemblerOutput) + << attrTagS(_BasicRuntimeChecks, tool.BasicRuntimeChecks) + << attrTagT(_BrowseInformation, tool.BrowseInformation) + << attrTagS(_BrowseInformationFile, tool.BrowseInformationFile) + << attrTagT(_BufferSecurityCheck, tool.BufferSecurityCheck) + << attrTagS(_CallingConvention, tool.CallingConvention) + << attrTagS(_CompileAs, tool.CompileAs) + << attrTagS(_CompileAsManaged, tool.CompileAsManaged) + << attrTagT(_CreateHotpatchableImage, tool.CreateHotpatchableImage) + << attrTagS(_DebugInformationFormat, tool.DebugInformationFormat) + << attrTagT(_DisableLanguageExtensions, tool.DisableLanguageExtensions) + << attrTagX(_DisableSpecificWarnings, tool.DisableSpecificWarnings, ";") + << attrTagS(_EnableEnhancedInstructionSet, tool.EnableEnhancedInstructionSet) + << attrTagT(_EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations) + << attrTagT(_EnablePREfast, tool.EnablePREfast) + << attrTagS(_ErrorReporting, tool.ErrorReporting) + << attrTagS(_ExceptionHandling, tool.ExceptionHandling) + << attrTagT(_ExpandAttributedSource, tool.ExpandAttributedSource) + << attrTagS(_FavorSizeOrSpeed, tool.FavorSizeOrSpeed) + << attrTagT(_FloatingPointExceptions, tool.FloatingPointExceptions) + << attrTagS(_FloatingPointModel, tool.FloatingPointModel) + << attrTagT(_ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope) + << attrTagX(_ForcedIncludeFiles, tool.ForcedIncludeFiles, ";") + << attrTagX(_ForcedUsingFiles, tool.ForcedUsingFiles, ";") + << attrTagT(_FunctionLevelLinking, tool.FunctionLevelLinking) + << attrTagT(_GenerateXMLDocumentationFiles, tool.GenerateXMLDocumentationFiles) + << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrTagS(_InlineFunctionExpansion, tool.InlineFunctionExpansion) + << attrTagT(_IntrinsicFunctions, tool.IntrinsicFunctions) + << attrTagT(_MinimalRebuild, tool.MinimalRebuild) + << attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation) + << attrTagS(_ObjectFileName, tool.ObjectFileName) + << attrTagX(_ObjectFiles, tool.ObjectFiles, ";") + << attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName) + << attrTagT(_OmitFramePointers, tool.OmitFramePointers) + << attrTagT(_OpenMPSupport, tool.OpenMPSupport) + << attrTagS(_Optimization, tool.Optimization) + << attrTagS(_PrecompiledHeader, tool.PrecompiledHeader) + << attrTagS(_PrecompiledHeaderFile, tool.PrecompiledHeaderFile) + << attrTagS(_PrecompiledHeaderOutputFile, tool.PrecompiledHeaderOutputFile) + << attrTagT(_PreprocessKeepComments, tool.PreprocessKeepComments) + << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") + << attrTagS(_PreprocessOutputPath, tool.PreprocessOutputPath) + << attrTagT(_PreprocessSuppressLineNumbers, tool.PreprocessSuppressLineNumbers) + << attrTagT(_PreprocessToFile, tool.PreprocessToFile) + << attrTagS(_ProgramDataBaseFileName, tool.ProgramDataBaseFileName) + << attrTagS(_ProcessorNumber, tool.ProcessorNumber) + << attrTagS(_RuntimeLibrary, tool.RuntimeLibrary) + << attrTagT(_RuntimeTypeInfo, tool.RuntimeTypeInfo) + << attrTagT(_ShowIncludes, tool.ShowIncludes) + << attrTagT(_SmallerTypeCheck, tool.SmallerTypeCheck) + << attrTagT(_StringPooling, tool.StringPooling) + << attrTagS(_StructMemberAlignment, tool.StructMemberAlignment) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrTagS(_TreatSpecificWarningsAsErrors, tool.TreatSpecificWarningsAsErrors) + << attrTagT(_TreatWarningAsError, tool.TreatWarningAsError) + << attrTagT(_TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType) + << attrTagT(_UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions) + << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") + << attrTagT(_UseFullPaths, tool.UseFullPaths) + << attrTagT(_UseUnicodeForAssemblerListing, tool.UseUnicodeForAssemblerListing) + << attrTagS(_WarningLevel, tool.WarningLevel) + << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) + << attrTagS(_XMLDocumentationFileName, tool.XMLDocumentationFileName) + << closetag(_CLCompile); +} + +bool VCXCLCompilerTool::parseOption(const char* option) +{ + // skip index 0 ('/' or '-') + char first = option[1]; + char second = option[2]; + char third = option[3]; + char fourth = option[4]; + bool found = true; + + switch (first) { + case '?': + qWarning("Generator: Option '/?' : MSVC.NET projects do not support outputting help info"); + found = false; + break; + case '@': + qWarning("Generator: Option '/@': MSVC.NET projects do not support the use of a response file"); + found = false; + break; + case 'l': + qWarning("Generator: Option '/link': qmake generator does not support passing link options through the compiler tool"); + found = false; + break; + case 'A': + if(second != 'I') { + found = false; + break; + } + AdditionalUsingDirectories += option+3; + break; + case 'C': + PreprocessKeepComments = _True; + break; + case 'D': + PreprocessorDefinitions += option+2; + break; + case 'E': + if(second == 'H') { + QString opt(option); + if (opt.endsWith("EHa")) + ExceptionHandling = "Async"; + else if (opt.endsWith("EHsc")) + ExceptionHandling = "Sync"; + else if (opt.endsWith("EHs")) + ExceptionHandling = "SyncCThrow"; + else { + ExceptionHandling = "false"; + } + break; + }else if(second == 'P') { + PreprocessSuppressLineNumbers = _True; + } + found = false; + break; + case 'F': + if(second <= '9' && second >= '0') { + AdditionalOptions += option; + break; + } else { + switch (second) { + case 'A': + if(third == 'c') { + AssemblerOutput = "AssemblyAndMachineCode"; + if(fourth == 's') + AssemblerOutput = "All"; + } else if(third == 's') { + AssemblerOutput = "AssemblyAndSourceCode"; + } else if(third == 'u') { + UseUnicodeForAssemblerListing = _True; + } else { + AssemblerOutput = "AssemblyCode"; + } + break; + case 'a': + AssemblerListingLocation = option+3; + break; + case 'C': + UseFullPaths = _True; + break; + case 'd': + ProgramDataBaseFileName = option+3; + break; + case 'I': + ForcedIncludeFiles += option+3; + break; + case 'i': + PreprocessOutputPath += option+3; + break; + case 'm': + AdditionalOptions += option; + break; + case 'R': + BrowseInformation = _True; + BrowseInformationFile = option+3; + break; + case 'r': + BrowseInformation = _True; + BrowseInformationFile = option+3; + break; + case 'U': + ForcedUsingFiles += option+3; + break; + case 'o': + ObjectFileName = option+3; + break; + case 'p': + PrecompiledHeaderOutputFile = option+3; + break; + case 'x': + ExpandAttributedSource = _True; + break; + default: + found = false; + break; + } + } + break; + case 'G': + switch (second) { + case 'F': + StringPooling = _True; + break; + case 'L': + WholeProgramOptimization = _True; + if(third == '-') + WholeProgramOptimization = _False; + break; + case 'R': + RuntimeTypeInfo = _True; + if(third == '-') + RuntimeTypeInfo = _False; + break; + case 'S': + BufferSecurityCheck = _True; + if(third == '-') + BufferSecurityCheck = _False; + break; + case 'T': + EnableFiberSafeOptimizations = _True; + break; + case 'd': + CallingConvention = "Cdecl"; + break; + case 'm': + MinimalRebuild = _True; + if(third == '-') + MinimalRebuild = _False; + break; + case 'r': + CallingConvention = "FastCall"; + break; + case 'y': + FunctionLevelLinking = _True; + break; + case 'z': + CallingConvention = "StdCall"; + break; + default: + found = false; + break; + } + break; + case 'H': + AdditionalOptions += option; + break; + case 'I': + AdditionalIncludeDirectories += option+2; + break; + case 'L': + if(second == 'D') { + AdditionalOptions += option; + break; + } + found = false; + break; + case 'M': + if(second == 'D') { + RuntimeLibrary = "MultiThreadedDLL"; + if(third == 'd') + RuntimeLibrary = "MultiThreadedDebugDLL"; + break; + } else if(second == 'P') { + MultiProcessorCompilation = _True; + ProcessorNumber = option+3; + break; + } else if(second == 'T') { + RuntimeLibrary = "MultiThreaded"; + if(third == 'd') + RuntimeLibrary = "MultiThreadedDebug"; + break; + } + found = false; + break; + case 'O': + switch (second) { + case '1': + Optimization = "MinSpace"; + break; + case '2': + Optimization = "MaxSpeed"; + break; + case 'b': + if(third == '0') + InlineFunctionExpansion = "Disabled"; + else if(third == '1') + InlineFunctionExpansion = "OnlyExplicitInline"; + else if(third == '2') + InlineFunctionExpansion = "AnySuitable"; + else + found = false; + break; + case 'd': + Optimization = "Disabled"; + break; + case 'i': + IntrinsicFunctions = _True; + break; + case 'p': + if(third == 'e') + OpenMPSupport = _True; + else + found = false; + break; + case 's': + FavorSizeOrSpeed = "Size"; + break; + case 't': + FavorSizeOrSpeed = "Speed"; + break; + case 'x': + Optimization = "Full"; + break; + case 'y': + OmitFramePointers = _True; + if(third == '-') + OmitFramePointers = _False; + break; + default: + found = false; + break; + } + break; + case 'P': + PreprocessToFile = _True; + break; + case 'Q': + if(second == 'I') { + AdditionalOptions += option; + break; + } + found = false; + break; + case 'R': + if(second == 'T' && third == 'C') { + if(fourth == '1') + BasicRuntimeChecks = "EnableFastChecks"; + else if(fourth == 'c') + SmallerTypeCheck = _True; + else if(fourth == 's') + BasicRuntimeChecks = "StackFrameRuntimeCheck"; + else if(fourth == 'u') + BasicRuntimeChecks = "UninitializedLocalUsageCheck"; + else + found = false; break; + } + break; + case 'T': + if(second == 'C') { + CompileAs = "CompileAsC"; + } else if(second == 'P') { + CompileAs = "CompileAsCpp"; + } else { + qWarning("Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake"); + found = false; break; + } + break; + case 'U': + UndefinePreprocessorDefinitions += option+2; + break; + case 'V': + AdditionalOptions += option; + break; + case 'W': + switch (second) { + case 'a': + WarningLevel = "EnableAllWarnings"; + break; + case '4': + WarningLevel = "Level4"; + break; + case '3': + WarningLevel = "Level3"; + break; + case '2': + WarningLevel = "Level2"; + break; + case '1': + WarningLevel = "Level1"; + break; + case '0': + WarningLevel = "TurnOffAllWarnings"; + break; + case 'L': + AdditionalOptions += option; + break; + case 'X': + TreatWarningAsError = _True; + break; + case 'p': + if(third == '6' && fourth == '4') { + // Deprecated for VS2010 but can be used under Additional Options. + AdditionalOptions += option; + break; + } + // Fallthrough + default: + found = false; break; + } + break; + case 'X': + IgnoreStandardIncludePath = _True; + break; + case 'Y': + switch (second) { + case '\0': + case '-': + AdditionalOptions += option; + break; + case 'c': + PrecompiledHeader = "Create"; + PrecompiledHeaderFile = option+3; + break; + case 'd': + case 'l': + AdditionalOptions += option; + break; + case 'u': + PrecompiledHeader = "Use"; + PrecompiledHeaderFile = option+3; + break; + default: + found = false; break; + } + break; + case 'Z': + switch (second) { + case '7': + DebugInformationFormat = "OldStyle"; + break; + case 'I': + DebugInformationFormat = "EditAndContinue"; + break; + case 'i': + DebugInformationFormat = "ProgramDatabase"; + break; + case 'l': + OmitDefaultLibName = _True; + break; + case 'a': + DisableLanguageExtensions = _True; + break; + case 'e': + DisableLanguageExtensions = _False; + break; + case 'c': + if(third == ':') { + const char *c = option + 4; + // Go to the end of the option + while ( *c != '\0' && *c != ' ' && *c != '-') + ++c; + if(fourth == 'f') + ForceConformanceInForLoopScope = ((*c) == '-' ? _False : _True); + else if(fourth == 'w') + TreatWChar_tAsBuiltInType = ((*c) == '-' ? _False : _True); + else + found = false; + } else { + found = false; break; + } + break; + case 'g': + case 'm': + case 's': + AdditionalOptions += option; + break; + case 'p': + switch (third) + { + case '\0': + case '1': + StructMemberAlignment = "1Byte"; + if(fourth == '6') + StructMemberAlignment = "16Bytes"; + break; + case '2': + StructMemberAlignment = "2Bytes"; + break; + case '4': + StructMemberAlignment = "4Bytes"; + break; + case '8': + StructMemberAlignment = "8Bytes"; + break; + default: + found = false; break; + } + break; + default: + found = false; break; + } + break; + case 'a': + if (second == 'r' && third == 'c' && fourth == 'h') { + if (option[5] == ':') { + const char *o = option; + if (o[6] == 'S' && o[7] == 'S' && o[8] == 'E') { + EnableEnhancedInstructionSet = o[9] == '2' ? "StreamingSIMDExtensions2" : "StreamingSIMDExtensions"; + break; + } + } + } else if (second == 'n' && third == 'a' && fourth == 'l') { + EnablePREfast = _True; + break; + } + found = false; + break; + case 'b': // see http://msdn.microsoft.com/en-us/library/fwkeyyhe%28VS.100%29.aspx + if (second == 'i' && third == 'g' && fourth == 'o') { + const char *o = option; + if (o[5] == 'b' && o[6] == 'j') { + AdditionalOptions += option; + break; + } + } + found = false; + break; + case 'c': + if(second == 'l') { + if(*(option+5) == 'p') { + CompileAsManaged = "Pure"; + } else if(*(option+5) == 's') { + CompileAsManaged = "Safe"; + } else if(*(option+5) == 'o') { + CompileAsManaged = "OldSyntax"; + } else { + CompileAsManaged = "true"; + } + } else { + found = false; + break; + } + break; + case 'd': + if(second != 'o' && third == 'c') { + GenerateXMLDocumentationFiles = _True; + XMLDocumentationFileName += option+4; + break; + } + found = false; + break; + case 'e': + if (second == 'r' && third == 'r' && fourth == 'o') { + if (option[12] == ':') { + if ( option[13] == 'n') { + ErrorReporting = "None"; + } else if (option[13] == 'p') { + ErrorReporting = "Prompt"; + } else if (option[13] == 'q') { + ErrorReporting = "Queue"; + } else if (option[13] == 's') { + ErrorReporting = "Send"; + } else { + found = false; + } + break; + } + } + found = false; + break; + case 'f': + if(second == 'p' && third == ':') { + // Go to the end of the option + const char *c = option + 4; + while (*c != '\0' && *c != ' ' && *c != '-') + ++c; + switch (fourth) { + case 'e': + FloatingPointExceptions = ((*c) == '-' ? _False : _True); + break; + case 'f': + FloatingPointModel = "Fast"; + break; + case 'p': + FloatingPointModel = "Precise"; + break; + case 's': + FloatingPointModel = "Strict"; + break; + default: + found = false; + break; + } + } + break; + case 'h': + if(second == 'o' && third == 't' && fourth == 'p') { + CreateHotpatchableImage = _True; + break; + } + qWarning("Generator: Option '/help': MSVC.NET projects do not support outputting help info"); + found = false; + break; + case 'n': + if(second == 'o' && third == 'l' && fourth == 'o') { + SuppressStartupBanner = _True; + break; + } + found = false; + break; + case 'o': + if (second == 'p' && third == 'e' && fourth == 'n') { + OpenMPSupport = _True; + break; + } + found = false; + break; + case 's': + if(second == 'h' && third == 'o' && fourth == 'w') { + ShowIncludes = _True; + break; + } + found = false; + break; + case 'u': + UndefineAllPreprocessorDefinitions = _True; + break; + case 'v': + if(second == 'd' || second == 'm') { + AdditionalOptions += option; + break; + } + found = false; + break; + case 'w': + switch (second) { + case 'd': + DisableSpecificWarnings += option+3; + break; + case 'e': + TreatSpecificWarningsAsErrors = option+3; + break; + default: + AdditionalOptions += option; + } + break; + default: + AdditionalOptions += option; + break; + } + if(!found) { + warn_msg(WarnLogic, "Could not parse Compiler option: %s, added as AdditionalOption", option); + AdditionalOptions += option; + } + return true; +} + +// VCLinkerTool ----------------------------------------------------- +VCXLinkerTool::VCXLinkerTool() + : AllowIsolation(unset), + AssemblyDebug(unset), + DataExecutionPrevention(unset), + DelaySign(unset), + EnableCOMDATFolding(unset), + EnableUAC(unset), + FixedBaseAddress(unset), + GenerateDebugInformation(unset), + GenerateManifest(unset), + GenerateMapFile(unset), + HeapCommitSize(-1), + HeapReserveSize(-1), + IgnoreAllDefaultLibraries(unset), + IgnoreEmbeddedIDL(unset), + IgnoreImportLibrary(_True), + ImageHasSafeExceptionHandlers(unset), + LargeAddressAware(unset), + LinkDLL(unset), + LinkIncremental(unset), + LinkStatus(unset), + MapExports(unset), + NoEntryPoint(unset), + OptimizeReferences(unset), + PreventDllBinding(unset), + RandomizedBaseAddress(unset), + RegisterOutput(unset), + SectionAlignment(-1), + SetChecksum(unset), + //StackCommitSize(-1), + //StackReserveSize(-1), + SupportNobindOfDelayLoadedDLL(unset), + SupportUnloadOfDelayLoadedDLL(unset), + SuppressStartupBanner(unset), + SwapRunFromCD(unset), + SwapRunFromNet(unset), + TerminalServerAware(unset), + TreatLinkerWarningAsErrors(unset), + TurnOffAssemblyGeneration(unset), + TypeLibraryResourceID(0), + UACUIAccess(unset) +{ +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXLinkerTool &tool) +{ + return xml + << tag(_Link) + << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") + << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") + << attrTagX(_AdditionalManifestDependencies, tool.AdditionalManifestDependencies, ";") + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrTagX(_AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly, ";") + << attrTagT(_AllowIsolation, tool.AllowIsolation) + << attrTagT(_AssemblyDebug, tool.AssemblyDebug) + << attrTagX(_AssemblyLinkResource, tool.AssemblyLinkResource, ";") + << attrTagS(_BaseAddress, tool.BaseAddress) + << attrTagS(_CLRImageType, tool.CLRImageType) + << attrTagS(_CLRSupportLastError, tool.CLRSupportLastError) + << attrTagS(_CLRThreadAttribute, tool.CLRThreadAttribute) + << attrTagS(_CLRUnmanagedCodeCheck, tool.CLRUnmanagedCodeCheck) + << attrTagS(_CreateHotPatchableImage, tool.CreateHotPatchableImage) + << attrTagT(_DataExecutionPrevention, tool.DataExecutionPrevention) + << attrTagX(_DelayLoadDLLs, tool.DelayLoadDLLs, ";") + << attrTagT(_DelaySign, tool.DelaySign) + << attrTagS(_Driver, tool.Driver) + << attrTagX(_EmbedManagedResourceFile, tool.EmbedManagedResourceFile, ";") + << attrTagT(_EnableCOMDATFolding, tool.EnableCOMDATFolding) + << attrTagT(_EnableUAC, tool.EnableUAC) + << attrTagS(_EntryPointSymbol, tool.EntryPointSymbol) + << attrTagT(_FixedBaseAddress, tool.FixedBaseAddress) + << attrTagS(_ForceFileOutput, tool.ForceFileOutput) + << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") + << attrTagS(_FunctionOrder, tool.FunctionOrder) + << attrTagT(_GenerateDebugInformation, tool.GenerateDebugInformation) + << attrTagT(_GenerateManifest, tool.GenerateManifest) + << attrTagT(_GenerateMapFile, tool.GenerateMapFile) + << attrTagL(_HeapCommitSize, tool.HeapCommitSize, /*ifNot*/ -1) + << attrTagL(_HeapReserveSize, tool.HeapReserveSize, /*ifNot*/ -1) + << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) + << attrTagT(_IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL) + << attrTagT(_IgnoreImportLibrary, tool.IgnoreImportLibrary) + << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreSpecificDefaultLibraries, ";") + << attrTagT(_ImageHasSafeExceptionHandlers, tool.ImageHasSafeExceptionHandlers) + << attrTagS(_ImportLibrary, tool.ImportLibrary) + << attrTagS(_KeyContainer, tool.KeyContainer) + << attrTagS(_KeyFile, tool.KeyFile) + << attrTagT(_LargeAddressAware, tool.LargeAddressAware) + << attrTagT(_LinkDLL, tool.LinkDLL) + << attrTagS(_LinkErrorReporting, tool.LinkErrorReporting) + << attrTagT(_LinkIncremental, tool.LinkIncremental) + << attrTagT(_LinkStatus, tool.LinkStatus) + << attrTagS(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) + << attrTagS(_ManifestFile, tool.ManifestFile) + << attrTagT(_MapExports, tool.MapExports) + << attrTagS(_MapFileName, tool.MapFileName) + << attrTagS(_MergedIDLBaseFileName, tool.MergedIDLBaseFileName) + << attrTagS(_MergeSections, tool.MergeSections) + << attrTagS(_MidlCommandFile, tool.MidlCommandFile) + << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) + << attrTagS(_MSDOSStubFileName, tool.MSDOSStubFileName) + << attrTagT(_NoEntryPoint, tool.NoEntryPoint) + << attrTagT(_OptimizeReferences, tool.OptimizeReferences) + << attrTagS(_OutputFile, tool.OutputFile) + << attrTagT(_PreventDllBinding, tool.PreventDllBinding) + << attrTagS(_Profile, tool.Profile) + << attrTagS(_ProfileGuidedDatabase, tool.ProfileGuidedDatabase) + << attrTagS(_ProgramDatabaseFile, tool.ProgramDatabaseFile) + << attrTagT(_RandomizedBaseAddress, tool.RandomizedBaseAddress) + << attrTagT(_RegisterOutput, tool.RegisterOutput) + << attrTagL(_SectionAlignment, tool.SectionAlignment, /*ifNot*/ -1) + << attrTagT(_SetChecksum, tool.SetChecksum) + << attrTagS(_ShowProgress, tool.ShowProgress) + << attrTagS(_SpecifySectionAttributes, tool.SpecifySectionAttributes) + << attrTagS(_StackCommitSize, tool.StackCommitSize) + << attrTagS(_StackReserveSize, tool.StackReserveSize) + << attrTagS(_StripPrivateSymbols, tool.StripPrivateSymbols) + << attrTagS(_SubSystem, tool.SubSystem) + << attrTagT(_SupportNobindOfDelayLoadedDLL, tool.SupportNobindOfDelayLoadedDLL) + << attrTagT(_SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrTagT(_SwapRunFromCD, tool.SwapRunFromCD) + << attrTagT(_SwapRunFromNet, tool.SwapRunFromNet) + << attrTagS(_TargetMachine, tool.TargetMachine) + << attrTagT(_TerminalServerAware, tool.TerminalServerAware) + << attrTagT(_TreatLinkerWarningAsErrors, tool.TreatLinkerWarningAsErrors) + << attrTagT(_TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration) + << attrTagS(_TypeLibraryFile, tool.TypeLibraryFile) + << attrTagL(_TypeLibraryResourceID, tool.TypeLibraryResourceID, /*ifNot*/ 0) + << attrTagS(_UACExecutionLevel, tool.UACExecutionLevel) + << attrTagT(_UACUIAccess, tool.UACUIAccess) + << attrTagS(_Version, tool.Version) + << closetag(_Link); +} + +// Hashing routine to do fast option lookups ---- +// Slightly rewritten to stop on ':' ',' and '\0' +// Original routine in qtranslator.cpp ---------- +static uint elfHash(const char* name) +{ + const uchar *k; + uint h = 0; + uint g; + + if(name) { + k = (const uchar *) name; + while((*k) && + (*k)!= ':' && + (*k)!=',' && + (*k)!=' ') { + h = (h << 4) + *k++; + if((g = (h & 0xf0000000)) != 0) + h ^= g >> 24; + h &= ~g; + } + } + if(!h) + h = 1; + return h; +} + +//#define USE_DISPLAY_HASH +#ifdef USE_DISPLAY_HASH +static void displayHash(const char* str) +{ + printf("case 0x%07x: // %s\n break;\n", elfHash(str), str); +} +#endif + +bool VCXLinkerTool::parseOption(const char* option) +{ +#ifdef USE_DISPLAY_HASH + // Main options + displayHash("/ALIGN"); displayHash("/ALLOWBIND"); displayHash("/ASSEMBLYMODULE"); + displayHash("/ASSEMBLYRESOURCE"); displayHash("/BASE"); displayHash("/DEBUG"); + displayHash("/DEF"); displayHash("/DEFAULTLIB"); displayHash("/DELAY"); + displayHash("/DELAYLOAD"); displayHash("/DLL"); displayHash("/DRIVER"); + displayHash("/ENTRY"); displayHash("/EXETYPE"); displayHash("/EXPORT"); + displayHash("/FIXED"); displayHash("/FORCE"); displayHash("/HEAP"); + displayHash("/IDLOUT"); displayHash("/IGNORE"); displayHash("/IGNOREIDL"); displayHash("/IMPLIB"); + displayHash("/INCLUDE"); displayHash("/INCREMENTAL"); displayHash("/LARGEADDRESSAWARE"); + displayHash("/LIBPATH"); displayHash("/LTCG"); displayHash("/MACHINE"); + displayHash("/MAP"); displayHash("/MAPINFO"); displayHash("/MERGE"); + displayHash("/MIDL"); displayHash("/NOASSEMBLY"); displayHash("/NODEFAULTLIB"); + displayHash("/NOENTRY"); displayHash("/NOLOGO"); displayHash("/OPT"); + displayHash("/ORDER"); displayHash("/OUT"); displayHash("/PDB"); + displayHash("/PDBSTRIPPED"); displayHash("/RELEASE"); displayHash("/SECTION"); + displayHash("/STACK"); displayHash("/STUB"); displayHash("/SUBSYSTEM"); + displayHash("/SWAPRUN"); displayHash("/TLBID"); displayHash("/TLBOUT"); + displayHash("/TSAWARE"); displayHash("/VERBOSE"); displayHash("/VERSION"); + displayHash("/VXD"); displayHash("/WS "); displayHash("/libpath"); + +#endif +#ifdef USE_DISPLAY_HASH + // Sub options + displayHash("UNLOAD"); displayHash("NOBIND"); displayHash("no"); displayHash("NOSTATUS"); displayHash("STATUS"); + displayHash("AM33"); displayHash("ARM"); displayHash("CEE"); displayHash("EBC"); displayHash("IA64"); displayHash("X86"); displayHash("X64"); displayHash("M32R"); + displayHash("MIPS"); displayHash("MIPS16"); displayHash("MIPSFPU"); displayHash("MIPSFPU16"); displayHash("MIPSR41XX"); displayHash("PPC"); + displayHash("SH3"); displayHash("SH3DSP"); displayHash("SH4"); displayHash("SH5"); displayHash("THUMB"); displayHash("TRICORE"); displayHash("EXPORTS"); + displayHash("LINES"); displayHash("REF"); displayHash("NOREF"); displayHash("ICF"); displayHash("WIN98"); displayHash("NOWIN98"); + displayHash("CONSOLE"); displayHash("EFI_APPLICATION"); displayHash("EFI_BOOT_SERVICE_DRIVER"); displayHash("EFI_ROM"); displayHash("EFI_RUNTIME_DRIVER"); displayHash("NATIVE"); + displayHash("POSIX"); displayHash("WINDOWS"); displayHash("WINDOWSCE"); displayHash("NET"); displayHash("CD"); displayHash("NO"); +#endif + bool found = true; + switch (elfHash(option)) { + case 0x6b21972: // /DEFAULTLIB:library + case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] + case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] + case 0x3dc3455: // /IGNORE:number,number,number,number ### NOTE: This one is undocumented, but it is even used by Microsoft. + // In recent versions of the Microsoft linker they have disabled this undocumented feature. + case 0x0034bc4: // /VXD + AdditionalOptions += option; + break; + case 0x3360dbe: // /ALIGN[:number] + SectionAlignment = QString(option+7).toLongLong(); + break; + case 0x1485c34: // /ALLOWBIND[:NO] + if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) + PreventDllBinding = _False; + else + PreventDllBinding = _True; + break; + case 0x312011e: // /ALLOWISOLATION[:NO] + if(*(option+15) == ':' && (*(option+16) == 'n' || *(option+16) == 'N')) + AllowIsolation = _False; + else + AllowIsolation = _True; + break; + case 0x679c075: // /ASSEMBLYMODULE:filename + AddModuleNamesToAssembly += option+15; + break; + case 0x75f35f7: // /ASSEMBLYDEBUG[:DISABLE] + if(*(option+14) == ':' && (*(option+15) == 'D')) + AssemblyDebug = _False; + else + AssemblyDebug = _True; + break; + case 0x43294a5: // /ASSEMBLYLINKRESOURCE:filename + AssemblyLinkResource += option+22; + break; + case 0x062d065: // /ASSEMBLYRESOURCE:filename + EmbedManagedResourceFile += option+18; + break; + case 0x0336675: // /BASE:{address | @filename,key} + // Do we need to do a manual lookup when '@filename,key'? + // Seems BaseAddress only can contain the location... + // We don't use it in Qt, so keep it simple for now + BaseAddress = option+6; + break; + case 0x63bf065: // /CLRIMAGETYPE:{IJW|PURE|SAFE} + if(*(option+14) == 'I') + CLRImageType = "ForceIJWImage"; + else if(*(option+14) == 'P') + CLRImageType = "ForcePureILImage"; + else if(*(option+14) == 'S') + CLRImageType = "ForceSafeILImage"; + break; + case 0x5f2a6a2: // /CLRSUPPORTLASTERROR{:NO | SYSTEMDLL} + if(*(option+20) == ':') { + if(*(option+21) == 'N') { + CLRSupportLastError = "Disabled"; + } else if(*(option+21) == 'S') { + CLRSupportLastError = "SystemDlls"; + } + } else { + CLRSupportLastError = "Enabled"; + } + break; + case 0xc7984f5: // /CLRTHREADATTRIBUTE:{STA|MTA|NONE} + if(*(option+20) == 'N') + CLRThreadAttribute = "DefaultThreadingAttribute"; + else if(*(option+20) == 'M') + CLRThreadAttribute = "MTAThreadingAttribute"; + else if(*(option+20) == 'S') + CLRThreadAttribute = "STAThreadingAttribute"; + break; + case 0xa8c637b: // /CLRUNMANAGEDCODECHECK[:NO] + if(*(option+23) == 'N') + CLRUnmanagedCodeCheck = _False; + else + CLRUnmanagedCodeCheck = _True; + break; + case 0x3389797: // /DEBUG + GenerateDebugInformation = _True; + break; + case 0x0033896: // /DEF:filename + ModuleDefinitionFile = option+5; + break; + case 0x338a069: // /DELAY:{UNLOAD | NOBIND} + if(*(option+7) == 'U') + SupportNobindOfDelayLoadedDLL = _True; + else if(*(option+7) == 'N') + SupportUnloadOfDelayLoadedDLL = _True; + break; + case 0x06f4bf4: // /DELAYLOAD:dllname + DelayLoadDLLs += option+11; + break; + case 0x06d451e: // /DELAYSIGN[:NO] + if(*(option+10) == ':' && (*(option+11) == 'n' || *(option+11) == 'N')) + DelaySign = _False; + else + DelaySign = _True; + break; + case 0x003390c: // /DLL + LinkDLL = _True; + break; + case 0x396ea92: // /DRIVER[:UPONLY | :WDM] + if((*(option+7) == ':') && (*(option+8) == 'U')) + Driver = "UpOnly"; + else if((*(option+7) == ':') && (*(option+8) == 'W')) + Driver = "WDM"; + else + Driver = "Driver"; + break; + case 0x2ee8415: // /DYNAMICBASE[:NO] + if(*(option+12) == ':' && (*(option+13) == 'n' || *(option+13) == 'N')) + RandomizedBaseAddress = _False; + else + RandomizedBaseAddress = _True; + break; + case 0x33a3979: // /ENTRY:function + EntryPointSymbol = option+7; + break; + case 0x4504334: // /ERRORREPORT:[ NONE | PROMPT | QUEUE | SEND ] + if(*(option+12) == ':' ) { + if(*(option+13) == 'N') + LinkErrorReporting = "NoErrorReport"; + else if(*(option+13) == 'P') + LinkErrorReporting = "PromptImmediately"; + else if(*(option+13) == 'Q') + LinkErrorReporting = "QueueForNextLogin"; + else if(*(option+13) == 'S') + LinkErrorReporting = "SendErrorReport"; + } + break; + case 0x33aec94: // /FIXED[:NO] + if(*(option+6) == ':' && (*(option+7) == 'n' || *(option+7) == 'N')) + FixedBaseAddress = _False; + else + FixedBaseAddress = _True; + break; + case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] + if(*(option+6) == ':' && *(option+7) == 'M' ) + ForceFileOutput = "MultiplyDefinedSymbolOnly"; + else if(*(option+6) == ':' && *(option+7) == 'U' ) + ForceFileOutput = "UndefinedSymbolOnly"; + else + ForceFileOutput = "Enabled"; + break; + case 0x96d4e4e: // /FUNCTIONPADMIN[:space] + if(*(option+15) == ':') { + if(*(option+16) == '5') + CreateHotPatchableImage = "X86Image"; + else if(*(option+16) == '6') + CreateHotPatchableImage = "X64Image"; + else if((*(option+16) == '1') && (*(option+17) == '6')) + CreateHotPatchableImage = "ItaniumImage"; + } else { + CreateHotPatchableImage = "Enabled"; + } + break; + case 0x033c960: // /HEAP:reserve[,commit] + { + QStringList both = QString(option+6).split(","); + HeapReserveSize = both[0].toLongLong(); + if(both.count() == 2) + HeapCommitSize = both[1].toLongLong(); + } + break; + case 0x3d91494: // /IDLOUT:[path\]filename + MergedIDLBaseFileName = option+8; + break; + case 0x345a04c: // /IGNOREIDL + IgnoreEmbeddedIDL = _True; + break; + case 0x3e250e2: // /IMPLIB:filename + ImportLibrary = option+8; + break; + case 0xe281ab5: // /INCLUDE:symbol + ForceSymbolReferences += option+9; + break; + case 0xb28103c: // /INCREMENTAL[:no] + if(*(option+12) == ':' && + (*(option+13) == 'n' || *(option+13) == 'N')) + LinkIncremental = _False; + else + LinkIncremental = _True; + break; + case 0x07f1ab2: // /KEYCONTAINER:name + KeyContainer = option+14; + break; + case 0xfadaf35: // /KEYFILE:filename + KeyFile = option+9; + break; + case 0x26e4675: // /LARGEADDRESSAWARE[:no] + if(*(option+18) == ':' && + *(option+19) == 'n') + LargeAddressAware = _False; + else + LargeAddressAware = _True; + break; + case 0x2f96bc8: // /libpath:dir + case 0x0d745c8: // /LIBPATH:dir + AdditionalLibraryDirectories += option+9; + break; + case 0x0341877: // /LTCG[:NOSTATUS|:STATUS] + config->WholeProgramOptimization = _True; + LinkTimeCodeGeneration = "UseLinkTimeCodeGeneration"; + if(*(option+5) == ':') { + const char* str = option+6; + if (*str == 'S') + LinkStatus = _True; + else if (*str == 'N') + LinkStatus = _False; +#ifndef Q_OS_WIN + else if (strncasecmp(str, "pginstrument", 12)) + LinkTimeCodeGeneration = "PGInstrument"; + else if (strncasecmp(str, "pgoptimize", 10)) + LinkTimeCodeGeneration = "PGOptimization"; + else if (strncasecmp(str, "pgupdate", 8 )) + LinkTimeCodeGeneration = "PGUpdate"; +#else + + else if (_stricmp(str, "pginstrument")) + LinkTimeCodeGeneration = "PGInstrument"; + else if (_stricmp(str, "pgoptimize")) + LinkTimeCodeGeneration = "PGOptimization"; + else if (_stricmp(str, "pgupdate")) + LinkTimeCodeGeneration = "PGUpdate"; +#endif + } + break; + case 0x379ED25: + case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE} + switch (elfHash(option+9)) { + case 0x0005bb6: // X86 + TargetMachine = "MachineX86"; + break; + case 0x0005b94: // X64 + TargetMachine = "MachineX64"; + break; + case 0x000466d: // ARM + TargetMachine = "MachineARM"; + break; + case 0x0004963: // EBC + TargetMachine = "MachineEBC"; + break; + case 0x004d494: // IA64 + TargetMachine = "MachineIA64"; + break; + case 0x0051e53: // MIPS + TargetMachine = "MachineMIPS"; + break; + case 0x51e5646: // MIPS16 + TargetMachine = "MachineMIPS16"; + break; + case 0x1e57b05: // MIPSFPU + TargetMachine = "MachineMIPSFPU"; + break; + case 0x57b09a6: // MIPSFPU16 + TargetMachine = "MachineMIPSFPU16"; + break; + case 0x00057b4: // SH4 + TargetMachine = "MachineSH4"; + break; + case 0x058da12: // THUMB + TargetMachine = "MachineTHUMB"; + break; + // put the others in AdditionalOptions... + case 0x0046063: // AM33 + case 0x0004795: // CEE + case 0x0050672: // M32R + case 0x5852738: // MIPSR41XX + case 0x0005543: // PPC + case 0x00057b3: // SH3 + case 0x57b7980: // SH3DSP + case 0x00057b5: // SH5 + case 0x96d8435: // TRICORE + default: + AdditionalOptions += option; + break; + } + break; + case 0x62d9e94: // /MANIFEST[:NO] + if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) + GenerateManifest = _False; + else + GenerateManifest = _True; + break; + case 0x8b64559: // /MANIFESTDEPENDENCY:manifest_dependency + AdditionalManifestDependencies += option+20; + break; + case 0xe9e8195: // /MANIFESTFILE:filename + ManifestFile = option+14; + break; + case 0x9e9fb83: // /MANIFESTUAC http://msdn.microsoft.com/en-us/library/bb384691%28VS.100%29.aspx + if ((*(option+12) == ':' && (*(option+13) == 'N' || *(option+13) == 'n'))) + EnableUAC = _False; + else if((*(option+12) == ':' && (*(option+13) == 'l' || *(option+14) == 'e'))) { // level + if(*(option+20) == 'a') + UACExecutionLevel = "AsInvoker"; + else if(*(option+20) == 'h') + UACExecutionLevel = "HighestAvailable"; + else if(*(option+20) == 'r') + UACExecutionLevel = "RequireAdministrator"; + } else if((*(option+12) == ':' && (*(option+13) == 'u' || *(option+14) == 'i'))) { // uiAccess + if(*(option+22) == 't') + UACUIAccess = _True; + else + UACUIAccess = _False; + } else if((*(option+12) == ':' && (*(option+13) == 'f' || *(option+14) == 'r'))) { // fragment + AdditionalOptions += option; + }else + EnableUAC = _True; + break; + case 0x0034160: // /MAP[:filename] + GenerateMapFile = _True; + if (option[4] == ':') + MapFileName = option+5; + break; + case 0x164e1ef: // /MAPINFO:{EXPORTS} + if(*(option+9) == 'E') + MapExports = _True; + break; + case 0x341a6b5: // /MERGE:from=to + MergeSections = option+7; + break; + case 0x0341d8c: // /MIDL:@file + MidlCommandFile = option+7; + break; + case 0x84e2679: // /NOASSEMBLY + TurnOffAssemblyGeneration = _True; + break; + case 0x2b21942: // /NODEFAULTLIB[:library] + if(*(option+13) == '\0') + IgnoreAllDefaultLibraries = _True; + else + IgnoreSpecificDefaultLibraries += option+14; + break; + case 0x33a3a39: // /NOENTRY + NoEntryPoint = _True; + break; + case 0x434138f: // /NOLOGO + SuppressStartupBanner = _True; + break; + case 0xc841054: // /NXCOMPAT[:NO] + if ((*(option+9) == ':' && (*(option+10) == 'N' || *(option+10) == 'n'))) + DataExecutionPrevention = _False; + else + DataExecutionPrevention = _True; + break; + case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} + { + char third = *(option+7); + switch (third) { + case 'F': // REF + if(*(option+5) == 'R') { + OptimizeReferences = _True; + } else { // ICF[=iterations] + EnableCOMDATFolding = _True; + // [=iterations] case is not documented + } + break; + case 'R': // NOREF + OptimizeReferences = _False; + break; + case 'I': // NOICF + EnableCOMDATFolding = _False; + break; + default: + found = false; + } + } + break; + case 0x34468a2: // /ORDER:@filename + FunctionOrder = option+8; + break; + case 0x00344a4: // /OUT:filename + OutputFile = option+5; + break; + case 0x0034482: // /PDB:filename + ProgramDatabaseFile = option+5; + break; + case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name + StripPrivateSymbols = option+13; + break; + case 0x00344b4: // /PGD:filename + ProfileGuidedDatabase = option+5; + break; + case 0x573af45: // /PROFILE + Profile = _True; + break; + case 0x6a09535: // /RELEASE + SetChecksum = _True; + break; + case 0x75AA4D8: // /SAFESEH:{NO} + { + if(*(option+8) == ':' && *(option+9) == 'N') + ImageHasSafeExceptionHandlers = _False; + else + ImageHasSafeExceptionHandlers = _True; + } + break; + case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] + SpecifySectionAttributes = option+9; + break; + case 0x348857b: // /STACK:reserve[,commit] + { + QStringList both = QString(option+7).split(","); + StackReserveSize = both[0].toLongLong(); + if(both.count() == 2) + StackCommitSize = both[1].toLongLong(); + } + break; + case 0x0348992: // /STUB:filename + MSDOSStubFileName = option+6; + break; + case 0x9B3C00D: + case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]] + { + // Split up in subsystem, and version number + QStringList both = QString(option+11).split(","); + switch (elfHash(both[0].toLatin1())) { + case 0x8438445: // CONSOLE + SubSystem = "Console"; + break; + case 0xbe29493: // WINDOWS + SubSystem = "Windows"; + break; + case 0x5268ea5: // NATIVE + SubSystem = "Native"; + break; + case 0x240949e: // EFI_APPLICATION + SubSystem = "EFI Application"; + break; + case 0xe617652: // EFI_BOOT_SERVICE_DRIVER + SubSystem = "EFI Boot Service Driver"; + break; + case 0x9af477d: // EFI_ROM + SubSystem = "EFI ROM"; + break; + case 0xd34df42: // EFI_RUNTIME_DRIVER + SubSystem = "EFI Runtime"; + break; + case 0x2949c95: // WINDOWSCE + SubSystem = "WindowsCE"; + break; + case 0x05547e8: // POSIX + SubSystem = "POSIX"; + break; + // The following are undocumented, so add them to AdditionalOptions + case 0x4B69795: // windowsce + AdditionalOptions += option; + break; + default: + found = false; + } + } + break; + case 0x8b654de: // /SWAPRUN:{NET | CD} + if(*(option+9) == 'N') + SwapRunFromNet = _True; + else if(*(option+9) == 'C') + SwapRunFromCD = _True; + else + found = false; + break; + case 0x34906d4: // /TLBID:id + TypeLibraryResourceID = QString(option+7).toLongLong(); + break; + case 0x4907494: // /TLBOUT:[path\]filename + TypeLibraryFile = option+8; + break; + case 0x976b525: // /TSAWARE[:NO] + if(*(option+8) == ':') + TerminalServerAware = _False; + else + TerminalServerAware = _True; + break; + case 0xaa67735: // /VERBOSE[:ICF |:LIB |:REF |:SAFESEH] + if(*(option+9) == ':') { + if (*(option+10) == 'I') { + ShowProgress = "LinkVerboseICF"; + } else if ( *(option+10) == 'L') { + ShowProgress = "LinkVerboseLib"; + } else if ( *(option+10) == 'R') { + ShowProgress = "LinkVerboseREF"; + } else if ( *(option+10) == 'S') { + ShowProgress = "LinkVerboseSAFESEH"; + } else if ( *(option+10) == 'C') { + ShowProgress = "LinkVerboseCLR"; + } + } else { + ShowProgress = "LinkVerbose"; + } + break; + case 0xaa77f7e: // /VERSION:major[.minor] + Version = option+9; + break; + case 0x0034c50: // /WS[:NO] + if(*(option+3) == ':') + TreatLinkerWarningAsErrors = _False; + else + TreatLinkerWarningAsErrors = _True; + break; + default: + AdditionalOptions += option; + break; + } + if(!found) { + warn_msg(WarnLogic, "Could not parse Linker options: %s, added as AdditionalOption", option); + AdditionalOptions += option; + } + return found; +} + +// VCMIDLTool ------------------------------------------------------- +VCXMIDLTool::VCXMIDLTool() + : ApplicationConfigurationMode(unset), + ErrorCheckAllocations(unset), + ErrorCheckBounds(unset), + ErrorCheckEnumRange(unset), + ErrorCheckRefPointers(unset), + ErrorCheckStubData(unset), + GenerateStublessProxies(unset), + GenerateTypeLibrary(unset), + IgnoreStandardIncludePath(unset), + LocaleID(-1), + MkTypLibCompatible(unset), + SuppressCompilerWarnings(unset), + SuppressStartupBanner(unset), + ValidateAllParameters(unset), + WarnAsError(unset) +{ +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXMIDLTool &tool) +{ + return xml + << tag(_Midl) + << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrTagT(_ApplicationConfigurationMode, tool.ApplicationConfigurationMode) + << attrTagS(_ClientStubFile, tool.ClientStubFile) + << attrTagS(_CPreprocessOptions, tool.CPreprocessOptions) + << attrTagS(_DefaultCharType, tool.DefaultCharType) + << attrTagS(_DLLDataFileName, tool.DLLDataFileName) + << attrTagS(_EnableErrorChecks, tool.EnableErrorChecks) + << attrTagT(_ErrorCheckAllocations, tool.ErrorCheckAllocations) + << attrTagT(_ErrorCheckBounds, tool.ErrorCheckBounds) + << attrTagT(_ErrorCheckEnumRange, tool.ErrorCheckEnumRange) + << attrTagT(_ErrorCheckRefPointers, tool.ErrorCheckRefPointers) + << attrTagT(_ErrorCheckStubData, tool.ErrorCheckStubData) + << attrTagS(_GenerateClientFiles, tool.GenerateClientFiles) + << attrTagS(_GenerateServerFiles, tool.GenerateServerFiles) + << attrTagT(_GenerateStublessProxies, tool.GenerateStublessProxies) + << attrTagT(_GenerateTypeLibrary, tool.GenerateTypeLibrary) + << attrTagS(_HeaderFileName, tool.HeaderFileName) + << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrTagS(_InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName) + << attrTagL(_LocaleID, tool.LocaleID, /*ifNot*/ -1) + << attrTagT(_MkTypLibCompatible, tool.MkTypLibCompatible) + << attrTagS(_OutputDirectory, tool.OutputDirectory) + << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") + << attrTagS(_ProxyFileName, tool.ProxyFileName) + << attrTagS(_RedirectOutputAndErrors, tool.RedirectOutputAndErrors) + << attrTagS(_ServerStubFile, tool.ServerStubFile) + << attrTagS(_StructMemberAlignment, tool.StructMemberAlignment) + << attrTagT(_SuppressCompilerWarnings, tool.SuppressCompilerWarnings) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrTagS(_TargetEnvironment, tool.TargetEnvironment) + << attrTagS(_TypeLibFormat, tool.TypeLibFormat) + << attrTagS(_TypeLibraryName, tool.TypeLibraryName) + << attrTagX(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions, ";") + << attrTagT(_ValidateAllParameters, tool.ValidateAllParameters) + << attrTagT(_WarnAsError, tool.WarnAsError) + << attrTagS(_WarningLevel, tool.WarningLevel) + << closetag(_Midl); +} + +bool VCXMIDLTool::parseOption(const char* option) +{ +#ifdef USE_DISPLAY_HASH + displayHash("/D name[=def]"); displayHash("/I directory-list"); displayHash("/Oi"); + displayHash("/Oic"); displayHash("/Oicf"); displayHash("/Oif"); displayHash("/Os"); + displayHash("/U name"); displayHash("/WX"); displayHash("/W{0|1|2|3|4}"); + displayHash("/Zp {N}"); displayHash("/Zs"); displayHash("/acf filename"); + displayHash("/align {N}"); displayHash("/app_config"); displayHash("/c_ext"); + displayHash("/char ascii7"); displayHash("/char signed"); displayHash("/char unsigned"); + displayHash("/client none"); displayHash("/client stub"); displayHash("/confirm"); + displayHash("/cpp_cmd cmd_line"); displayHash("/cpp_opt options"); + displayHash("/cstub filename"); displayHash("/dlldata filename"); displayHash("/env win32"); + displayHash("/env win64"); displayHash("/error all"); displayHash("/error allocation"); + displayHash("/error bounds_check"); displayHash("/error enum"); displayHash("/error none"); + displayHash("/error ref"); displayHash("/error stub_data"); displayHash("/h filename"); + displayHash("/header filename"); displayHash("/iid filename"); displayHash("/lcid"); + displayHash("/mktyplib203"); displayHash("/ms_ext"); displayHash("/ms_union"); + displayHash("/msc_ver <nnnn>"); displayHash("/newtlb"); displayHash("/no_cpp"); + displayHash("/no_def_idir"); displayHash("/no_default_epv"); displayHash("/no_format_opt"); + displayHash("/no_warn"); displayHash("/nocpp"); displayHash("/nologo"); displayHash("/notlb"); + displayHash("/o filename"); displayHash("/oldnames"); displayHash("/oldtlb"); + displayHash("/osf"); displayHash("/out directory"); displayHash("/pack {N}"); + displayHash("/prefix all"); displayHash("/prefix client"); displayHash("/prefix server"); + displayHash("/prefix switch"); displayHash("/protocol all"); displayHash("/protocol dce"); + displayHash("/protocol ndr64"); displayHash("/proxy filename"); displayHash("/robust"); + displayHash("/rpcss"); displayHash("/savePP"); displayHash("/server none"); + displayHash("/server stub"); displayHash("/sstub filename"); displayHash("/syntax_check"); + displayHash("/target {system}"); displayHash("/tlb filename"); displayHash("/use_epv"); + displayHash("/win32"); displayHash("/win64"); +#endif + bool found = true; + int offset = 0; + switch(elfHash(option)) { + case 0x0000334: // /D name[=def] + PreprocessorDefinitions += option+3; + break; + case 0x0000339: // /I directory-list + AdditionalIncludeDirectories += option+3; + break; + case 0x0345f96: // /Oicf + case 0x00345f6: // /Oif + GenerateStublessProxies = _True; + break; + case 0x0000345: // /U name + UndefinePreprocessorDefinitions += option+3; + break; + case 0x00034c8: // /WX + WarnAsError = _True; + break; + case 0x3582fde: // /align {N} + offset = 3; // Fallthrough + case 0x0003510: // /Zp {N} + switch (*(option+offset+4)) { + case '1': + StructMemberAlignment = (*(option+offset+5) == '\0') ? "1" : "16"; + break; + case '2': + StructMemberAlignment = "2"; + break; + case '4': + StructMemberAlignment = "4"; + break; + case '8': + StructMemberAlignment = "8"; + break; + default: + found = false; + } + break; + case 0x5b1cb97: // /app_config + ApplicationConfigurationMode = _True; + break; + case 0x0359e82: // /char {ascii7|signed|unsigned} + switch(*(option+6)) { + case 'a': + DefaultCharType = "Ascii"; + break; + case 's': + DefaultCharType = "Signed"; + break; + case 'u': + DefaultCharType = "Unsigned"; + break; + default: + found = false; + } + break; + case 0x5a2fc64: // /client {none|stub} + if(*(option+8) == 's') + GenerateClientFiles = "Stub"; + else + GenerateClientFiles = "None"; + break; + case 0xa766524: // /cpp_opt options + CPreprocessOptions += option+9; + break; + case 0x35aabb2: // /cstub filename + ClientStubFile = option+7; + break; + case 0xb32abf1: // /dlldata filename + DLLDataFileName = option + 9; + break; + case 0x0035c56: // /env {win32|ia64|x64} + if(*(option+7) == 'w' && *(option+10) == '3') + TargetEnvironment = "Win32"; + else if(*(option+7) == 'i') + TargetEnvironment = "Itanium"; + else if(*(option+7) == 'x') + TargetEnvironment = "X64"; + else + AdditionalOptions += option; + break; + case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data} + EnableErrorChecks = midlEnableCustom; + switch (*(option+7)) { + case '\0': + EnableErrorChecks = "EnableCustom"; + break; + case 'a': + if(*(option+10) == '\0') + EnableErrorChecks = "All"; + else + ErrorCheckAllocations = _True; + break; + case 'b': + ErrorCheckBounds = _True; + break; + case 'e': + ErrorCheckEnumRange = _True; + break; + case 'n': + EnableErrorChecks = "None"; + break; + case 'r': + ErrorCheckRefPointers = _True; + break; + case 's': + ErrorCheckStubData = _True; + break; + default: + found = false; + } + break; + case 0x5eb7af2: // /header filename + offset = 5; + case 0x0000358: // /h filename + HeaderFileName = option + offset + 3; + break; + case 0x0035ff4: // /iid filename + InterfaceIdentifierFileName = option+5; + break; + case 0x64b7933: // /mktyplib203 + MkTypLibCompatible = _True; + break; + case 0x64ceb12: // /newtlb + TypeLibFormat = "NewFormat"; + break; + case 0x8e0b0a2: // /no_def_idir + IgnoreStandardIncludePath = _True; + break; + case 0x65635ef: // /nologo + SuppressStartupBanner = _True; + break; + case 0x695e9f4: // /no_robust + ValidateAllParameters = _False; + break; + case 0x3656b22: // /notlb + GenerateTypeLibrary = _True; + break; + case 0x556dbee: // /no_warn + SuppressCompilerWarnings = _True; + break; + case 0x000035f: // /o filename + RedirectOutputAndErrors = option+3; + break; + case 0x662bb12: // /oldtlb + TypeLibFormat = "OldFormat"; + break; + case 0x00366c4: // /out directory + OutputDirectory = option+5; + break; + case 0x36796f9: // /proxy filename + ProxyFileName = option+7; + break; + case 0x6959c94: // /robust + ValidateAllParameters = _True; + break; + case 0x69c9cf2: // /server {none|stub} + if(*(option+8) == 's') + GenerateServerFiles = "Stub"; + else + GenerateServerFiles = "None"; + break; + case 0x36aabb2: // /sstub filename + ServerStubFile = option+7; + break; + case 0x0036b22: // /tlb filename + TypeLibraryName = option+5; + break; + case 0x36e0162: // /win32 + TargetEnvironment = "Win32"; + break; + case 0x36e0194: // /win64 + TargetEnvironment = "Itanium"; + break; + case 0x0003459: // /Oi + case 0x00345f3: // /Oic + case 0x0003463: // /Os + case 0x0003513: // /Zs + case 0x0035796: // /acf filename + case 0x3595cf4: // /c_ext + case 0xa64d3dd: // /confirm + case 0xa765b64: // /cpp_cmd cmd_line + case 0x03629f4: // /lcid + case 0x6495cc4: // /ms_ext + case 0x96c7a1e: // /ms_union + case 0x4996fa2: // /msc_ver <nnnn> + case 0x6555a40: // /no_cpp + case 0xf64d6a6: // /no_default_epv + case 0x6dd9384: // /no_format_opt + case 0x3655a70: // /nocpp + case 0x2b455a3: // /oldnames + case 0x0036696: // /osf + case 0x036679b: // /pack {N} + case 0x678bd38: // /prefix {all|client|server|switch} + case 0x96b702c: // /protocol {all|dce|ndr64} + case 0x3696aa3: // /rpcss + case 0x698ca60: // /savePP + case 0xce9b12b: // /syntax_check + case 0xc9b5f16: // /use_epv + AdditionalOptions += option; + break; + default: + // /W{0|1|2|3|4} case + if(*(option+1) == 'W') { + switch (*(option+2)) { + case '0': + WarningLevel = "0"; + break; + case '1': + WarningLevel = "1"; + break; + case '2': + WarningLevel = "2"; + break; + case '3': + WarningLevel = "3"; + break; + case '4': + WarningLevel = "4"; + break; + default: + found = false; + } + } + break; + } + if(!found) + warn_msg(WarnLogic, "Could not parse MIDL option: %s", option); + return true; +} + +// VCLibrarianTool -------------------------------------------------- +VCXLibrarianTool::VCXLibrarianTool() + : IgnoreAllDefaultLibraries(unset), + LinkTimeCodeGeneration(unset), + SuppressStartupBanner(_True), + TreatLibWarningAsErrors(unset), + Verbose(unset) +{ +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXLibrarianTool &tool) +{ + return xml + << tag(_Link) + << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") + << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") + << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") + << attrTagS(_DisplayLibrary, tool.DisplayLibrary) + << attrTagS(_ErrorReporting, tool.ErrorReporting) + << attrTagX(_ExportNamedFunctions, tool.ExportNamedFunctions, ";") + << attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";") + << attrTagT(_IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries) + << attrTagX(_IgnoreSpecificDefaultLibraries, tool.IgnoreSpecificDefaultLibraries, ";") + << attrTagT(_LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration) + << attrTagS(_ModuleDefinitionFile, tool.ModuleDefinitionFile) + << attrTagS(_Name, tool.Name) + << attrTagS(_OutputFile, tool.OutputFile) + << attrTagX(_RemoveObjects, tool.RemoveObjects, ";") + << attrTagS(_SubSystem, tool.SubSystem) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrTagS(_TargetMachine, tool.TargetMachine) + << attrTagT(_TreatLibWarningAsErrors, tool.TreatLibWarningAsErrors) + << attrTagT(_Verbose, tool.Verbose) + << closetag(_Link); +} + +// VCCustomBuildTool ------------------------------------------------ +VCXCustomBuildTool::VCXCustomBuildTool() +{ + ToolName = "VCXCustomBuildTool"; +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXCustomBuildTool &tool) +{ + // The code below offers two ways to split custom build step commands. + // Normally the $$escape_expand(\n\t) is used in a project file, which is correctly translated + // in all generators. However, if you use $$escape_expand(\n\r) (or \n\h) instead, the VCPROJ + // generator will instead of binding the commands with " && " will insert a proper newline into + // the VCPROJ file. We sometimes use this method of splitting commands if the custom buildstep + // contains a command-line which is too big to run on certain OS. + QString cmds; + int end = tool.CommandLine.count(); + for(int i = 0; i < end; ++i) { + QString cmdl = tool.CommandLine.at(i); + if (cmdl.contains("\r\t")) { + if (i == end - 1) + cmdl = cmdl.trimmed(); + cmdl.replace("\r\t", " && "); + } else if (cmdl.contains("\r\n")) { + ; + } else if (cmdl.contains("\r\\h")) { + // The above \r\n should work, but doesn't, so we have this hack + cmdl.replace("\r\\h", "\r\n"); + } else { + if (i < end - 1) + cmdl += " && "; + } + cmds += cmdl; + } + + if ( !tool.AdditionalDependencies.isEmpty() ) + { + xml << tag("AdditionalInputs") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << valueTagDefX(tool.AdditionalDependencies, "AdditionalInputs", ";"); + } + + if( !cmds.isEmpty() ) + { + xml << tag("Command") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << valueTag(cmds); + } + + if ( !tool.Description.isEmpty() ) + { + xml << tag("Message") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << valueTag(tool.Description); + } + + if ( !tool.Outputs.isEmpty() ) + { + xml << tag("Outputs") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.ConfigName)) + << valueTagDefX(tool.Outputs, "Outputs", ";"); + } + + return xml; +} + +// VCResourceCompilerTool ------------------------------------------- +VCXResourceCompilerTool::VCXResourceCompilerTool() + : IgnoreStandardIncludePath(unset), + NullTerminateStrings(unset), + ShowProgress(unset), + SuppressStartupBanner(unset) +{ + PreprocessorDefinitions = QStringList("NDEBUG"); +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXResourceCompilerTool &tool) +{ + return xml + << tag(_ResourceCompile) + << attrTagX(_AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories, ";") + << attrTagS(_AdditionalOptions, tool.AdditionalOptions) + << attrTagS(_Culture, tool.Culture) + << attrTagT(_IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath) + << attrTagT(_NullTerminateStrings, tool.NullTerminateStrings) + << attrTagX(_PreprocessorDefinitions, tool.PreprocessorDefinitions, ";") + << attrTagS(_ResourceOutputFileName, tool.ResourceOutputFileName) + << attrTagT(_ShowProgress, tool.ShowProgress) + << attrTagT(_SuppressStartupBanner, tool.SuppressStartupBanner) + << attrTagS(_TrackerLogDirectory, tool.TrackerLogDirectory) + << attrTagS(_UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions) + << closetag(_ResourceCompile); +} + +// VCXDeploymentTool -------------------------------------------- +VCXDeploymentTool::VCXDeploymentTool() +{ + DeploymentTag = "DeploymentTool"; + RemoteDirectory = ""; +} + +// http://msdn.microsoft.com/en-us/library/sa69he4t.aspx +XmlOutput &operator<<(XmlOutput &xml, const VCXDeploymentTool &tool) +{ + if (tool.AdditionalFiles.isEmpty()) + return xml; + return xml + << tag(tool.DeploymentTag) + << closetag(tool.DeploymentTag); +} + +// VCEventTool ------------------------------------------------- +XmlOutput &operator<<(XmlOutput &xml, const VCXEventTool &tool) +{ + return xml + << tag(tool.EventName) + << attrTagS(_Command, tool.CommandLine) + << attrTagS(_Message, tool.Description) + << closetag(tool.EventName); +} + +// VCXPostBuildEventTool --------------------------------------------- +VCXPostBuildEventTool::VCXPostBuildEventTool() +{ + EventName = "PostBuildEvent"; +} + +// VCXPreBuildEventTool ---------------------------------------------- +VCXPreBuildEventTool::VCXPreBuildEventTool() +{ + EventName = "PreBuildEvent"; +} + +// VCXPreLinkEventTool ----------------------------------------------- +VCXPreLinkEventTool::VCXPreLinkEventTool() +{ + EventName = "PreLinkEvent"; +} + +// VCConfiguration -------------------------------------------------- + +VCXConfiguration::VCXConfiguration() + : ATLMinimizesCRunTimeLibraryUsage(unset), + BuildBrowserInformation(unset), + RegisterOutput(unset), + WholeProgramOptimization(unset) +{ + compiler.config = this; + linker.config = this; + idl.config = this; +} + +XmlOutput &operator<<(XmlOutput &xml, const VCXConfiguration &tool) +{ + xml << tag("PropertyGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Name)) + << attrTag("Label", "Configuration") + << attrTagS(_OutputDirectory, tool.OutputDirectory) + << attrTagT(_ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage) + << attrTagT(_BuildBrowserInformation, tool.BuildBrowserInformation) + << attrTagS(_CharacterSet, tool.CharacterSet) + << attrTagS(_ConfigurationType, tool.ConfigurationType) + << attrTagS(_DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean) + << attrTagS(_ImportLibrary, tool.ImportLibrary) + << attrTagS(_IntermediateDirectory, tool.IntermediateDirectory) + << attrTagS(_PrimaryOutput, tool.PrimaryOutput) + << attrTagS(_ProgramDatabase, tool.ProgramDatabase) + << attrTagT(_RegisterOutput, tool.RegisterOutput) + << attrTagS(_UseOfATL, tool.UseOfATL) + << attrTagS(_UseOfMfc, tool.UseOfMfc) + << attrTagT(_WholeProgramOptimization, tool.WholeProgramOptimization) + << closetag(); + return xml; +} +// VCXFilter --------------------------------------------------------- +VCXFilter::VCXFilter() + : ParseFiles(unset), + Config(0) +{ + useCustomBuildTool = false; + useCompilerTool = false; +} + +void VCXFilter::addFile(const QString& filename) +{ + Files += VCXFilterFile(filename); +} + +void VCXFilter::addFile(const VCXFilterFile& fileInfo) +{ + Files += VCXFilterFile(fileInfo); +} + +void VCXFilter::addFiles(const QStringList& fileList) +{ + for (int i = 0; i < fileList.count(); ++i) + addFile(fileList.at(i)); +} + +void VCXFilter::modifyPCHstage(QString str) +{ + bool autogenSourceFile = Project->autogenPrecompCPP; + bool pchThroughSourceFile = !Project->precompCPP.isEmpty(); + bool isCFile = false; + for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { + if (str.endsWith(*it)) { + isCFile = true; + break; + } + } + bool isHFile = str.endsWith(".h") && (str == Project->precompH); + bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP); + + if(!isCFile && !isHFile && !isCPPFile) + return; + + if(isHFile && pchThroughSourceFile) { + if (autogenSourceFile) { + useCustomBuildTool = true; + QString toFile(Project->precompCPP); + CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ..."; + CustomBuildTool.Outputs += toFile; + + QStringList lines; + CustomBuildTool.CommandLine += + "echo /*-------------------------------------------------------------------- >" + toFile; + lines << "* Precompiled header source file used by Visual Studio.NET to generate"; + lines << "* the .pch file."; + lines << "*"; + lines << "* Due to issues with the dependencies checker within the IDE, it"; + lines << "* sometimes fails to recompile the PCH file, if we force the IDE to"; + lines << "* create the PCH file directly from the header file."; + lines << "*"; + lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was"; + lines << "* specified, and is used as the common stdafx.cpp. The file is only"; + lines << "* generated when creating .vcxproj project files, and is not used for"; + lines << "* command line compilations by nmake."; + lines << "*"; + lines << "* WARNING: All changes made in this file will be lost."; + lines << "--------------------------------------------------------------------*/"; + lines << "#include \"" + Project->precompHFilename + "\""; + foreach(QString line, lines) + CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile; + } + return; + } + + useCompilerTool = true; + // Setup PCH options + CompilerTool.PrecompiledHeader = (isCFile ? "NotUsing" : "Create" ); + CompilerTool.PrecompiledHeaderFile = (isCPPFile ? QString("$(INHERIT)") : QString("$(NOINHERIT)")); + CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)"); +} + +bool VCXFilter::addExtraCompiler(const VCXFilterFile &info) +{ + const QStringList &extraCompilers = Project->extraCompilerSources.value(info.file); + if (extraCompilers.isEmpty()) + return false; + + QString inFile = info.file; + + // is the extracompiler rule on a file with a built in compiler? + const QStringList &objectMappedFile = Project->extraCompilerOutputs[inFile]; + bool hasBuiltIn = false; + if (!objectMappedFile.isEmpty()) { + hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile.at(0)); +// qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(" "))); + } + + CustomBuildTool.AdditionalDependencies.clear(); + CustomBuildTool.CommandLine.clear(); + CustomBuildTool.Description.clear(); + CustomBuildTool.Outputs.clear(); + CustomBuildTool.ToolPath.clear(); + CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool); + + for (int x = 0; x < extraCompilers.count(); ++x) { + const QString &extraCompilerName = extraCompilers.at(x); + + if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn) + continue; + + // All information about the extra compiler + QString tmp_out = Project->project->first(extraCompilerName + ".output"); + QString tmp_cmd = Project->project->variables()[extraCompilerName + ".commands"].join(" "); + QString tmp_cmd_name = Project->project->variables()[extraCompilerName + ".name"].join(" "); + QStringList tmp_dep = Project->project->variables()[extraCompilerName + ".depends"]; + QString tmp_dep_cmd = Project->project->variables()[extraCompilerName + ".depend_command"].join(" "); + QStringList vars = Project->project->variables()[extraCompilerName + ".variables"]; + QStringList configs = Project->project->variables()[extraCompilerName + ".CONFIG"]; + bool combined = configs.indexOf("combine") != -1; + + QString cmd, cmd_name, out; + QStringList deps, inputs; + // Variabel replacement of output name + out = Option::fixPathToTargetOS( + Project->replaceExtraCompilerVariables(tmp_out, inFile, QString()), + false); + + // If file has built-in compiler, we've swapped the input and output of + // the command, as we in Visual Studio cannot have a Custom Buildstep on + // a file which uses a built-in compiler. We would in this case only get + // the result from the extra compiler. If 'hasBuiltIn' is true, we know + // that we're actually on the _output_file_ of the result, and we + // therefore swap inFile and out below, since the extra-compiler still + // must see it as the original way. If the result also has a built-in + // compiler, too bad.. + if (hasBuiltIn) { + out = inFile; + inFile = objectMappedFile.at(0); + } + + // Dependency for the output + if(!tmp_dep.isEmpty()) + deps = tmp_dep; + if(!tmp_dep_cmd.isEmpty()) { + // Execute dependency command, and add every line as a dep + char buff[256]; + QString dep_cmd = Project->replaceExtraCompilerVariables(tmp_dep_cmd, Option::fixPathToLocalOS(inFile, true, false), out); + if(Project->canExecute(dep_cmd)) { + if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + QString indeps; + while(!feof(proc)) { + int read_in = (int)fread(buff, 1, 255, proc); + if(!read_in) + break; + indeps += QByteArray(buff, read_in); + } + QT_PCLOSE(proc); + if(!indeps.isEmpty()) { + QStringList extradeps = indeps.split(QLatin1Char('\n')); + for (int i = 0; i < extradeps.count(); ++i) { + QString dd = extradeps.at(i).simplified(); + if (!dd.isEmpty()) + deps += Project->fileFixify(dd); + } + } + } + } + } + for (int i = 0; i < deps.count(); ++i) + deps[i] = Option::fixPathToTargetOS( + Project->replaceExtraCompilerVariables(deps.at(i), inFile, out), + false).trimmed(); + // Command for file + if (combined) { + // Add dependencies for each file + QStringList tmp_in = Project->project->variables()[extraCompilerName + ".input"]; + for (int a = 0; a < tmp_in.count(); ++a) { + const QStringList &files = Project->project->variables()[tmp_in.at(a)]; + for (int b = 0; b < files.count(); ++b) { + deps += Project->findDependencies(files.at(b)); + inputs += Option::fixPathToTargetOS(files.at(b), false); + } + } + deps += inputs; // input files themselves too.. + + // Replace variables for command w/all input files + // ### join gives path issues with directories containing spaces! + cmd = Project->replaceExtraCompilerVariables(tmp_cmd, + inputs.join(" "), + out); + } else { + deps += inFile; // input file itself too.. + cmd = Project->replaceExtraCompilerVariables(tmp_cmd, + inFile, + out); + } + // Name for command + if(!tmp_cmd_name.isEmpty()) { + cmd_name = Project->replaceExtraCompilerVariables(tmp_cmd_name, inFile, out); + } else { + int space = cmd.indexOf(' '); + if(space != -1) + cmd_name = cmd.left(space); + else + cmd_name = cmd; + if((cmd_name[0] == '\'' || cmd_name[0] == '"') && + cmd_name[0] == cmd_name[cmd_name.length()-1]) + cmd_name = cmd_name.mid(1,cmd_name.length()-2); + } + + // Fixify paths + for (int i = 0; i < deps.count(); ++i) + deps[i] = Option::fixPathToTargetOS(deps[i], false); + + + // Output in info.additionalFile ----------- + if (!CustomBuildTool.Description.isEmpty()) + CustomBuildTool.Description += " & "; + CustomBuildTool.Description += cmd_name; + CustomBuildTool.CommandLine += cmd.trimmed().split("\n", QString::SkipEmptyParts); + int space = cmd.indexOf(' '); + QFileInfo finf(cmd.left(space)); + if (CustomBuildTool.ToolPath.isEmpty()) + CustomBuildTool.ToolPath += Option::fixPathToTargetOS(finf.path()); + CustomBuildTool.Outputs += out; + + deps += CustomBuildTool.AdditionalDependencies; + deps += cmd.left(cmd.indexOf(' ')); + // Make sure that all deps are only once + QMap<QString, bool> uniqDeps; + for (int c = 0; c < deps.count(); ++c) { + QString aDep = deps.at(c).trimmed(); + if (!aDep.isEmpty()) + uniqDeps[aDep] = false; + } + CustomBuildTool.AdditionalDependencies = uniqDeps.keys(); + } + + // Ensure that none of the output files are also dependencies. Or else, the custom buildstep + // will be rebuild every time, even if nothing has changed. + foreach(QString output, CustomBuildTool.Outputs) { + CustomBuildTool.AdditionalDependencies.removeAll(output); + } + + useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty(); + return useCustomBuildTool; +} + +bool VCXFilter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded) +{ + bool fileAdded = false; + + // Clearing each filter tool + useCustomBuildTool = false; + useCompilerTool = false; + CustomBuildTool = VCXCustomBuildTool(); + CompilerTool = VCXCLCompilerTool(); + + // Unset some default options + CompilerTool.BufferSecurityCheck = unset; + CompilerTool.DebugInformationFormat = ""; + CompilerTool.ExceptionHandling = ""; + //CompilerTool.Optimization = optimizeDefault; + CompilerTool.ProgramDataBaseFileName.clear(); + CompilerTool.RuntimeLibrary = ""; + //CompilerTool.WarningLevel = warningLevelUnknown; + CompilerTool.config = Config; + + bool inBuild = false; + VCXFilterFile info; + for (int i = 0; i < Files.count(); ++i) { + if (Files.at(i).file == filename) { + info = Files.at(i); + inBuild = true; + } + } + inBuild &= !info.excludeFromBuild; + + if (inBuild) { + addExtraCompiler(info); + if(Project->usePCH) + modifyPCHstage(info.file); + } else { + // Excluded files uses an empty compiler stage + if(info.excludeFromBuild) + useCompilerTool = true; + } + + // Actual XML output ---------------------------------- + if(useCustomBuildTool || useCompilerTool || !inBuild) { + + if (useCustomBuildTool) + { + CustomBuildTool.ConfigName = (*Config).Name; + + if ( !fileAllreadyAdded ) { + + fileAdded = true; + + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + + if ( filtername == "Form Files" || filtername == "Generated Files" || filtername == "Resource Files" ) + xml << attrTagS("FileType", "Document"); + } + + xml << CustomBuildTool; + } + + if ( !fileAdded && !fileAllreadyAdded ) + { + fileAdded = true; + + if (filtername == "Source Files") { + + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + + } else if(filtername == "Header Files") { + + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filtername == "Generated Files" || filtername == "Form Files") { + + if (filename.endsWith(".h")) { + + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filename.endsWith(".cpp")) { + + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else if(filename.endsWith(".res")) { + + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } else { + + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)) + << attrTagS("Filter", filtername); + + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } + } else if(filtername == "Root Files") { + + if (filename.endsWith(".rc")) { + + xmlFilter << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + + xml << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(filename)); + } + } + } + + if(!inBuild) { + + xml << tag("ExcludedFromBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) + << valueTag("true"); + } + + if (useCompilerTool) { + + if ( !CompilerTool.ForcedIncludeFiles.isEmpty() ) { + xml << tag("ForcedIncludeFiles") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) + << valueTagX(CompilerTool.ForcedIncludeFiles); + } + + if ( !CompilerTool.PrecompiledHeaderFile.isEmpty() ) { + + xml << tag("PrecompiledHeaderFile") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) + << valueTag(CompilerTool.PrecompiledHeaderFile); + } + + if ( !CompilerTool.PrecompiledHeader.isEmpty() ) { + + xml << tag("PrecompiledHeader") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg((*Config).Name)) + << valueTag(CompilerTool.PrecompiledHeader); + } + } + } + + return fileAdded; +} + + +// VCXProjectSingleConfig -------------------------------------------- +VCXFilter nullVCXFilter; +VCXFilter& VCXProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) +{ + for (int i = 0; i < ExtraCompilersFiles.count(); ++i) + if (ExtraCompilersFiles.at(i).Name == compilerName) + return ExtraCompilersFiles[i]; + return nullVCXFilter; +} + + +XmlOutput &operator<<(XmlOutput &xml, const VCXProjectSingleConfig &tool) +{ + xml.setIndentString(" "); + + xml << decl("1.0", "utf-8") + << tag("Project") + << attrTag("DefaultTargets","Build") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") + << tag("ItemGroup") + << attrTag("Label", "ProjectConfigurations"); + + xml << tag("ProjectConfiguration") + << attrTag("Include" , tool.Configuration.Name) + << tagValue("Configuration", tool.Configuration.ConfigurationName) + << tagValue("Platform", tool.PlatformName) + << closetag(); + + xml << closetag() + << tag("PropertyGroup") + << attrTag("Label", "Globals") + << tagValue("ProjectGuid", tool.ProjectGUID) + << tagValue("RootNamespace", tool.Name) + << tagValue("Keyword", tool.Keyword) + << closetag(); + + // config part. + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + + xml << tool.Configuration; + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + + // Extension settings + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionSettings") + << closetag(); + + // PropertySheets + xml << tag("ImportGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << attrTag("Label", "PropertySheets"); + + xml << tag("Import") + << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") + << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") + << closetag() + << closetag(); + + + // UserMacros + xml << tag("PropertyGroup") + << attrTag("Label", "UserMacros") + << closetag(); + + xml << tag("PropertyGroup"); + + if ( !tool.Configuration.OutputDirectory.isEmpty() ) { + xml<< tag("OutDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.OutputDirectory); + } + if ( !tool.Configuration.IntermediateDirectory.isEmpty() ) { + xml<< tag("IntDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.IntermediateDirectory); + } + if ( !tool.Configuration.TargetName.isEmpty() ) { + xml<< tag("TargetName") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTag(tool.Configuration.TargetName); + } + + if ( tool.Configuration.linker.IgnoreImportLibrary != unset) { + xml<< tag("IgnoreImportLibrary") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.linker.IgnoreImportLibrary); + } + + if ( tool.Configuration.linker.LinkIncremental != unset) { + xml<< tag("LinkIncremental") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.linker.LinkIncremental); + } + + if ( tool.Configuration.preBuild.UseInBuild != unset ) + { + xml<< tag("PreBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.preBuild.UseInBuild); + } + + if ( tool.Configuration.preLink.UseInBuild != unset ) + { + xml<< tag("PreLinkEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.preLink.UseInBuild); + } + + if ( tool.Configuration.postBuild.UseInBuild != unset ) + { + xml<< tag("PostBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)) + << valueTagT(tool.Configuration.postBuild.UseInBuild); + } + xml << closetag(); + + xml << tag("ItemDefinitionGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.Configuration.Name)); + + // ClCompile + xml << tool.Configuration.compiler; + + // Link + xml << tool.Configuration.linker; + + // Midl + xml << tool.Configuration.idl; + + // ResourceCompiler + xml << tool.Configuration.resource; + + // Post build event + if ( tool.Configuration.postBuild.UseInBuild != unset ) + xml << tool.Configuration.postBuild; + + // Pre build event + if ( tool.Configuration.preBuild.UseInBuild != unset ) + xml << tool.Configuration.preBuild; + + // Pre link event + if ( tool.Configuration.preLink.UseInBuild != unset ) + xml << tool.Configuration.preLink; + + xml << closetag(); + + QFile filterFile; + filterFile.setFileName(Option::output.fileName().append(".filters")); + filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + QTextStream ts(&filterFile); + XmlOutput xmlFilter(ts, XmlOutput::NoConversion); + + xmlFilter.setIndentString(" "); + + xmlFilter << decl("1.0", "utf-8") + << tag("Project") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + + xmlFilter << tag("ItemGroup"); + + VCXProject tempProj; + tempProj.SingleProjects += tool; + + tempProj.addFilters(xmlFilter, "Form Files"); + tempProj.addFilters(xmlFilter, "Generated Files"); + tempProj.addFilters(xmlFilter, "Header Files"); + tempProj.addFilters(xmlFilter, "LexYacc Files"); + tempProj.addFilters(xmlFilter, "Resource Files"); + tempProj.addFilters(xmlFilter, "Source Files"); + tempProj.addFilters(xmlFilter, "Translation Files"); + xmlFilter << closetag(); + + tempProj.outputFilter(xml, xmlFilter, "Source Files"); + tempProj.outputFilter(xml, xmlFilter, "Header Files"); + tempProj.outputFilter(xml, xmlFilter, "Generated Files"); + tempProj.outputFilter(xml, xmlFilter, "LexYacc Files"); + tempProj.outputFilter(xml, xmlFilter, "Translation Files"); + tempProj.outputFilter(xml, xmlFilter, "Form Files"); + tempProj.outputFilter(xml, xmlFilter, "Resource Files"); + + for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { + tempProj.outputFilter(xml, xmlFilter, tempProj.ExtraCompilers.at(x)); + } + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionTargets") + << closetag(); + + return xml; +} + + +// Tree file generation --------------------------------------------- +void XTreeNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter) { + + if (children.size()) { + // Filter + ChildrenMap::ConstIterator it, end = children.constEnd(); + if (!tagName.isEmpty()) { + xmlFilter << tag("Filter") + << attrTag("Include", tagName) + << attrTagS("Extensions", ""); + } + // First round, do nested filters + for (it = children.constBegin(); it != end; ++it) + if ((*it)->children.size()) + (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); + // Second round, do leafs + for (it = children.constBegin(); it != end; ++it) + if (!(*it)->children.size()) + (*it)->generateXML(xml, xmlFilter, it.key(), tool, filter); + + if (!tagName.isEmpty()) + xml << closetag("Filter"); + } else { + // Leaf + tool.outputFileConfigs(xml, xmlFilter, info, filter); + } +} + + +// Flat file generation --------------------------------------------- +void XFlatNode::generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &/*tagName*/, VCXProject &tool, const QString &filter) { + if (children.size()) { + ChildrenMapFlat::ConstIterator it = children.constBegin(); + ChildrenMapFlat::ConstIterator end = children.constEnd(); + xml << tag(_ItemGroup); + xmlFilter << tag(_ItemGroup); + for (; it != end; ++it) { + tool.outputFileConfigs(xml, xmlFilter, (*it), filter); + } + xml << closetag(); + xmlFilter << closetag(); + } +} + + +// VCXProject -------------------------------------------------------- +// Output all configurations (by filtername) for a file (by info) +// A filters config output is in VCXFilter.outputFileConfig() +void VCXProject::outputFileConfigs(XmlOutput &xml, + XmlOutput &xmlFilter, + const VCXFilterFile &info, + const QString &filtername) +{ + // We need to check if the file has any custom build step. + // If there is one then it has to be included with "CustomBuild Include" + bool fileAdded = false; + + for (int i = 0; i < SingleProjects.count(); ++i) { + VCXFilter filter; + if (filtername == "Root Files") { + filter = SingleProjects.at(i).RootFiles; + } else if (filtername == "Source Files") { + filter = SingleProjects.at(i).SourceFiles; + } else if (filtername == "Header Files") { + filter = SingleProjects.at(i).HeaderFiles; + } else if (filtername == "Generated Files") { + filter = SingleProjects.at(i).GeneratedFiles; + } else if (filtername == "LexYacc Files") { + filter = SingleProjects.at(i).LexYaccFiles; + } else if (filtername == "Translation Files") { + filter = SingleProjects.at(i).TranslationFiles; + } else if (filtername == "Form Files") { + filter = SingleProjects.at(i).FormFiles; + } else if (filtername == "Resource Files") { + filter = SingleProjects.at(i).ResourceFiles; + } else { + // ExtraCompilers + filter = SingleProjects[i].filterForExtraCompiler(filtername); + } + + if (filter.Config) // only if the filter is not empty + if (filter.outputFileConfig(xml, xmlFilter, info.file, filtername, fileAdded)) // only add it once. + fileAdded = true; + } + + if ( !fileAdded ) + { + if (filtername == "Source Files") { + + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + + } else if(filtername == "Header Files") { + + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } else if(filtername == "Generated Files" || filtername == "Form Files") { + + if (info.file.endsWith(".h")) { + + xmlFilter << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("ClInclude") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } else if(info.file.endsWith(".cpp")) { + + xmlFilter << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("ClCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } else if(info.file.endsWith(".res")) { + + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } else { + + xmlFilter << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("CustomBuild") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } + + } else if(filtername == "Root Files") { + + if (info.file.endsWith(".rc")) { + + xmlFilter << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + + xml << tag("ResourceCompile") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } + } else { + + xmlFilter << tag("None") + << attrTag("Include",Option::fixPathToLocalOS(info.file)) + << attrTagS("Filter", filtername); + + xml << tag("None") + << attrTag("Include",Option::fixPathToLocalOS(info.file)); + } + } + + xml << closetag(); + xmlFilter << closetag(); +} + +// outputs a given filter for all existing configurations of a project +void VCXProject::outputFilter(XmlOutput &xml, + XmlOutput &xmlFilter, + const QString &filtername) +{ + XNode *root; + if (SingleProjects.at(0).flat_files) + root = new XFlatNode; + else + root = new XTreeNode; + + QString name, extfilter; + triState parse; + + for (int i = 0; i < SingleProjects.count(); ++i) { + VCXFilter filter; + if (filtername == "Root Files") { + filter = SingleProjects.at(i).RootFiles; + } else if (filtername == "Source Files") { + filter = SingleProjects.at(i).SourceFiles; + } else if (filtername == "Header Files") { + filter = SingleProjects.at(i).HeaderFiles; + } else if (filtername == "Generated Files") { + filter = SingleProjects.at(i).GeneratedFiles; + } else if (filtername == "LexYacc Files") { + filter = SingleProjects.at(i).LexYaccFiles; + } else if (filtername == "Translation Files") { + filter = SingleProjects.at(i).TranslationFiles; + } else if (filtername == "Form Files") { + filter = SingleProjects.at(i).FormFiles; + } else if (filtername == "Resource Files") { + filter = SingleProjects.at(i).ResourceFiles; + } else { + // ExtraCompilers + filter = SingleProjects[i].filterForExtraCompiler(filtername); + } + + // Merge all files in this filter to root tree + for (int x = 0; x < filter.Files.count(); ++x) + root->addElement(filter.Files.at(x)); + + // Save filter setting from first filter. Next filters + // may differ but we cannot handle that. (ex. extfilter) + if (name.isEmpty()) { + name = filter.Name; + extfilter = filter.Filter; + parse = filter.ParseFiles; + } + } + + if (!root->hasElements()) + return; + + root->generateXML(xml, xmlFilter, "", *this, filtername); // output root tree +} + + +void VCXProject::addFilters(XmlOutput &xmlFilter, + const QString &filtername) +{ + bool added = false; + + for (int i = 0; i < SingleProjects.count(); ++i) { + VCXFilter filter; + if (filtername == "Root Files") { + filter = SingleProjects.at(i).RootFiles; + } else if (filtername == "Source Files") { + filter = SingleProjects.at(i).SourceFiles; + } else if (filtername == "Header Files") { + filter = SingleProjects.at(i).HeaderFiles; + } else if (filtername == "Generated Files") { + filter = SingleProjects.at(i).GeneratedFiles; + } else if (filtername == "LexYacc Files") { + filter = SingleProjects.at(i).LexYaccFiles; + } else if (filtername == "Translation Files") { + filter = SingleProjects.at(i).TranslationFiles; + } else if (filtername == "Form Files") { + filter = SingleProjects.at(i).FormFiles; + } else if (filtername == "Resource Files") { + filter = SingleProjects.at(i).ResourceFiles; + } else { + // ExtraCompilers + filter = SingleProjects[i].filterForExtraCompiler(filtername); + } + + if(!filter.Files.isEmpty() && !added) { + added = true; + xmlFilter << tag("Filter") + << attrTag("Include", filtername) + << attrTagS("UniqueIdentifier", filter.Guid) + << attrTagS("Extensions", filter.Filter) + << attrTagT("ParseFiles", filter.ParseFiles) + << closetag(); + } + } +} + + +XmlOutput &operator<<(XmlOutput &xml, VCXProject &tool) +{ + + if (tool.SingleProjects.count() == 0) { + warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); + return xml; + } + + xml.setIndentString(" "); + + xml << decl("1.0", "utf-8") + << tag("Project") + << attrTag("DefaultTargets","Build") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003") + << tag("ItemGroup") + << attrTag("Label", "ProjectConfigurations"); + + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ProjectConfiguration") + << attrTag("Include" , tool.SingleProjects.at(i).Configuration.Name) + << tagValue("Configuration", tool.SingleProjects.at(i).Configuration.ConfigurationName) + << tagValue("Platform", tool.SingleProjects.at(i).PlatformName) + << closetag(); + } + + xml << closetag() + << tag("PropertyGroup") + << attrTag("Label", "Globals") + << tagValue("ProjectGuid", tool.ProjectGUID) + << tagValue("RootNamespace", tool.Name) + << tagValue("Keyword", tool.Keyword) + << closetag(); + + // config part. + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + for (int i = 0; i < tool.SingleProjects.count(); ++i) + xml << tool.SingleProjects.at(i).Configuration; + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + + // Extension settings + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionSettings") + << closetag(); + + // PropertySheets + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ImportGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << attrTag("Label", "PropertySheets"); + + xml << tag("Import") + << attrTag("Project", "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props") + << attrTag("Condition", "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") + << closetag() + << closetag(); + } + + // UserMacros + xml << tag("PropertyGroup") + << attrTag("Label", "UserMacros") + << closetag(); + + xml << tag("PropertyGroup"); + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + + if ( !tool.SingleProjects.at(i).Configuration.OutputDirectory.isEmpty() ) { + xml << tag("OutDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.OutputDirectory); + } + if ( !tool.SingleProjects.at(i).Configuration.IntermediateDirectory.isEmpty() ) { + xml << tag("IntDir") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.IntermediateDirectory); + } + if ( !tool.SingleProjects.at(i).Configuration.TargetName.isEmpty() ) { + xml << tag("TargetName") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTag(tool.SingleProjects.at(i).Configuration.TargetName); + } + + if ( tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary != unset) { + xml << tag("IgnoreImportLibrary") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.linker.IgnoreImportLibrary); + } + + if ( tool.SingleProjects.at(i).Configuration.linker.LinkIncremental != unset) { + xml << tag("LinkIncremental") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.linker.LinkIncremental); + } + + if ( tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild != unset ) + { + xml << tag("PreBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild); + } + + if ( tool.SingleProjects.at(i).Configuration.preLink.UseInBuild != unset ) + { + xml << tag("PreLinkEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.preLink.UseInBuild); + } + + if ( tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild != unset ) + { + xml << tag("PostBuildEventUseInBuild") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)) + << valueTagT(tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild); + } + } + xml << closetag(); + + for (int i = 0; i < tool.SingleProjects.count(); ++i) { + xml << tag("ItemDefinitionGroup") + << attrTag("Condition", QString("'$(Configuration)|$(Platform)'=='%1'").arg(tool.SingleProjects.at(i).Configuration.Name)); + + // ClCompile + xml << tool.SingleProjects.at(i).Configuration.compiler; + + // Link + xml << tool.SingleProjects.at(i).Configuration.linker; + + // Midl + xml << tool.SingleProjects.at(i).Configuration.idl; + + // ResourceCompiler + xml << tool.SingleProjects.at(i).Configuration.resource; + + // Post build event + if ( tool.SingleProjects.at(i).Configuration.postBuild.UseInBuild != unset ) + xml << tool.SingleProjects.at(i).Configuration.postBuild; + + // Pre build event + if ( tool.SingleProjects.at(i).Configuration.preBuild.UseInBuild != unset ) + xml << tool.SingleProjects.at(i).Configuration.preBuild; + + // Pre link event + if ( tool.SingleProjects.at(i).Configuration.preLink.UseInBuild != unset ) + xml << tool.SingleProjects.at(i).Configuration.preLink; + + xml << closetag(); + } + + // The file filters are added in a separate file for MSBUILD. + QFile filterFile; + filterFile.setFileName(Option::output.fileName().append(".filters")); + filterFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + QTextStream ts(&filterFile); + XmlOutput xmlFilter(ts, XmlOutput::NoConversion); + + xmlFilter.setIndentString(" "); + + xmlFilter << decl("1.0", "utf-8") + << tag("Project") + << attrTag("ToolsVersion", "4.0") + << attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"); + + xmlFilter << tag("ItemGroup"); + + tool.addFilters(xmlFilter, "Form Files"); + tool.addFilters(xmlFilter, "Generated Files"); + tool.addFilters(xmlFilter, "Header Files"); + tool.addFilters(xmlFilter, "LexYacc Files"); + tool.addFilters(xmlFilter, "Resource Files"); + tool.addFilters(xmlFilter, "Source Files"); + tool.addFilters(xmlFilter, "Translation Files"); + xmlFilter << closetag(); + + tool.outputFilter(xml, xmlFilter, "Source Files"); + tool.outputFilter(xml, xmlFilter, "Header Files"); + tool.outputFilter(xml, xmlFilter, "Generated Files"); + tool.outputFilter(xml, xmlFilter, "LexYacc Files"); + tool.outputFilter(xml, xmlFilter, "Translation Files"); + tool.outputFilter(xml, xmlFilter, "Form Files"); + tool.outputFilter(xml, xmlFilter, "Resource Files"); + for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { + tool.outputFilter(xml, xmlFilter, tool.ExtraCompilers.at(x)); + } + tool.outputFilter(xml, xmlFilter, "Root Files"); + + xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + + xml << tag("ImportGroup") + << attrTag("Label", "ExtensionTargets") + << closetag(); + + return xml; +} + +QT_END_NAMESPACE diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h new file mode 100644 index 0000000000..567985df82 --- /dev/null +++ b/qmake/generators/win32/msbuild_objectmodel.h @@ -0,0 +1,708 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MSBUILD_OBJECTMODEL_H +#define MSBUILD_OBJECTMODEL_H + +#include "project.h" +#include "xmloutput.h" +#include "msvc_objectmodel.h" +#include <qatomic.h> +#include <qlist.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qmap.h> +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + + +class VCXConfiguration; +class VCXProject; + +class VCXCLCompilerTool : public VCToolBase +{ +public: + // Functions + VCXCLCompilerTool(); + virtual ~VCXCLCompilerTool(){} + bool parseOption(const char* option); + + // Variables + QStringList AdditionalIncludeDirectories; + QStringList AdditionalOptions; + QStringList AdditionalUsingDirectories; + QString AlwaysAppend; + QString AssemblerListingLocation; + QString AssemblerOutput; + QString BasicRuntimeChecks; + triState BrowseInformation; + QString BrowseInformationFile; + triState BufferSecurityCheck; + QString CallingConvention; + QString CompileAs; + QString CompileAsManaged; + triState CreateHotpatchableImage; + QString DebugInformationFormat; + triState DisableLanguageExtensions; + QStringList DisableSpecificWarnings; + QString EnableEnhancedInstructionSet; + triState EnableFiberSafeOptimizations; + triState EnablePREfast; + QString ErrorReporting; + QString ExceptionHandling; + triState ExpandAttributedSource; + QString FavorSizeOrSpeed; + triState FloatingPointExceptions; + QString FloatingPointModel; + triState ForceConformanceInForLoopScope; + QStringList ForcedIncludeFiles; + QStringList ForcedUsingFiles; + triState FunctionLevelLinking; + triState GenerateXMLDocumentationFiles; + triState IgnoreStandardIncludePath; + QString InlineFunctionExpansion; + triState IntrinsicFunctions; + triState MinimalRebuild; + triState MultiProcessorCompilation; + QString ObjectFileName; + QStringList ObjectFiles; + triState OmitDefaultLibName; + triState OmitFramePointers; + triState OpenMPSupport; + QString Optimization; + QString PrecompiledHeader; + QString PrecompiledHeaderFile; + QString PrecompiledHeaderOutputFile; + triState PreprocessKeepComments; + QStringList PreprocessorDefinitions; + QString PreprocessOutputPath; + triState PreprocessSuppressLineNumbers; + triState PreprocessToFile; + QString ProgramDataBaseFileName; + QString ProcessorNumber; + QString RuntimeLibrary; + triState RuntimeTypeInfo; + triState ShowIncludes; + triState SmallerTypeCheck; + triState StringPooling; + QString StructMemberAlignment; + triState SuppressStartupBanner; + QString TreatSpecificWarningsAsErrors; + triState TreatWarningAsError; + triState TreatWChar_tAsBuiltInType; + triState UndefineAllPreprocessorDefinitions; + QStringList UndefinePreprocessorDefinitions; + triState UseFullPaths; + triState UseUnicodeForAssemblerListing; + QString WarningLevel; + triState WholeProgramOptimization; + QString XMLDocumentationFileName; + + VCXConfiguration* config; +}; + +class VCXLinkerTool : public VCToolBase +{ +public: + // Functions + VCXLinkerTool(); + virtual ~VCXLinkerTool(){} + bool parseOption(const char* option); + + // Variables + QStringList AdditionalDependencies; + QStringList AdditionalLibraryDirectories; + QStringList AdditionalManifestDependencies; + QStringList AdditionalOptions; + QStringList AddModuleNamesToAssembly; + triState AllowIsolation; + triState AssemblyDebug; + QStringList AssemblyLinkResource; + QString BaseAddress; + QString CLRImageType; + QString CLRSupportLastError; + QString CLRThreadAttribute; + QString CLRUnmanagedCodeCheck; + QString CreateHotPatchableImage; + triState DataExecutionPrevention; + QStringList DelayLoadDLLs; + triState DelaySign; + QString Driver; + QStringList EmbedManagedResourceFile; + triState EnableCOMDATFolding; + triState EnableUAC; + QString EntryPointSymbol; + triState FixedBaseAddress; + QString ForceFileOutput; + QStringList ForceSymbolReferences; + QString FunctionOrder; + triState GenerateDebugInformation; + triState GenerateManifest; + triState GenerateMapFile; + qlonglong HeapCommitSize; + qlonglong HeapReserveSize; + triState IgnoreAllDefaultLibraries; + triState IgnoreEmbeddedIDL; + triState IgnoreImportLibrary; + QStringList IgnoreSpecificDefaultLibraries; + triState ImageHasSafeExceptionHandlers; + QString ImportLibrary; + QString KeyContainer; + QString KeyFile; + triState LargeAddressAware; + triState LinkDLL; + QString LinkErrorReporting; + triState LinkIncremental; + triState LinkStatus; + QString LinkTimeCodeGeneration; + QString ManifestFile; + triState MapExports; + QString MapFileName; + QString MergedIDLBaseFileName; + QString MergeSections; + QString MidlCommandFile; + QString ModuleDefinitionFile; + QString MSDOSStubFileName; + triState NoEntryPoint; + triState OptimizeReferences; + QString OutputFile; + triState PreventDllBinding; + QString Profile; + QString ProfileGuidedDatabase; + QString ProgramDatabaseFile; + triState RandomizedBaseAddress; + triState RegisterOutput; + qlonglong SectionAlignment; + triState SetChecksum; + QString ShowProgress; + QString SpecifySectionAttributes; + QString StackCommitSize; + QString StackReserveSize; + QString StripPrivateSymbols; + QString SubSystem; + triState SupportNobindOfDelayLoadedDLL; + triState SupportUnloadOfDelayLoadedDLL; + triState SuppressStartupBanner; + triState SwapRunFromCD; + triState SwapRunFromNet; + QString TargetMachine; + triState TerminalServerAware; + triState TreatLinkerWarningAsErrors; + triState TurnOffAssemblyGeneration; + QString TypeLibraryFile; + qlonglong TypeLibraryResourceID; + QString UACExecutionLevel; + triState UACUIAccess; + QString Version; + + + VCXConfiguration* config; +}; + +class VCXMIDLTool : public VCToolBase +{ +public: + // Functions + VCXMIDLTool(); + virtual ~VCXMIDLTool(){} + bool parseOption(const char* option); + + // Variables + QStringList AdditionalIncludeDirectories; + QStringList AdditionalOptions; + triState ApplicationConfigurationMode; + QString ClientStubFile; + QString CPreprocessOptions; + QString DefaultCharType; + QString DLLDataFileName; + QString EnableErrorChecks; + triState ErrorCheckAllocations; + triState ErrorCheckBounds; + triState ErrorCheckEnumRange; + triState ErrorCheckRefPointers; + triState ErrorCheckStubData; + QString GenerateClientFiles; + QString GenerateServerFiles; + triState GenerateStublessProxies; + triState GenerateTypeLibrary; + QString HeaderFileName; + triState IgnoreStandardIncludePath; + QString InterfaceIdentifierFileName; + qlonglong LocaleID; + triState MkTypLibCompatible; + QString OutputDirectory; + QStringList PreprocessorDefinitions; + QString ProxyFileName; + QString RedirectOutputAndErrors; + QString ServerStubFile; + QString StructMemberAlignment; + triState SuppressCompilerWarnings; + triState SuppressStartupBanner; + QString TargetEnvironment; + QString TypeLibFormat; + QString TypeLibraryName; + QStringList UndefinePreprocessorDefinitions; + triState ValidateAllParameters; + triState WarnAsError; + QString WarningLevel; + + VCXConfiguration* config; +}; + +class VCXLibrarianTool : public VCToolBase +{ +public: + // Functions + VCXLibrarianTool(); + virtual ~VCXLibrarianTool(){} + bool parseOption(const char*){ return false; }; + + // Variables + QStringList AdditionalDependencies; + QStringList AdditionalLibraryDirectories; + QStringList AdditionalOptions; + QString DisplayLibrary; + QString ErrorReporting; + QStringList ExportNamedFunctions; + QStringList ForceSymbolReferences; + triState IgnoreAllDefaultLibraries; + QStringList IgnoreSpecificDefaultLibraries; + triState LinkTimeCodeGeneration; + QString ModuleDefinitionFile; + QString Name; + QString OutputFile; + QStringList RemoveObjects; + QString SubSystem; + triState SuppressStartupBanner; + QString TargetMachine; + triState TreatLibWarningAsErrors; + triState Verbose; + +}; + +class VCXCustomBuildTool : public VCToolBase +{ +public: + // Functions + VCXCustomBuildTool(); + virtual ~VCXCustomBuildTool(){} + bool parseOption(const char*){ return false; }; + + // Variables + QStringList AdditionalDependencies; + QStringList CommandLine; + QString Description; + QStringList Outputs; + QString ToolName; + QString ToolPath; + QString ConfigName; +}; + +class VCXResourceCompilerTool : public VCToolBase +{ +public: + // Functions + VCXResourceCompilerTool(); + virtual ~VCXResourceCompilerTool(){} + bool parseOption(const char*){ return false; }; + + // Variables + QStringList AdditionalIncludeDirectories; + QString AdditionalOptions; + QString Culture; + triState IgnoreStandardIncludePath; + triState NullTerminateStrings; + QStringList PreprocessorDefinitions; + QString ResourceOutputFileName; + triState ShowProgress; + triState SuppressStartupBanner; + QString TrackerLogDirectory; + QString UndefinePreprocessorDefinitions; +}; + +class VCXDeploymentTool +{ +public: + // Functions + VCXDeploymentTool(); + virtual ~VCXDeploymentTool() {} + + // Variables + QString DeploymentTag; + QString RemoteDirectory; + QString AdditionalFiles; +}; + +class VCXEventTool : public VCToolBase +{ +protected: + // Functions + VCXEventTool() : UseInBuild(unset){}; + virtual ~VCXEventTool(){} + bool parseOption(const char*){ return false; }; + +public: + // Variables + QString CommandLine; + QString Description; + triState UseInBuild; + QString EventName; + QString ToolPath; +}; + +class VCXPostBuildEventTool : public VCXEventTool +{ +public: + VCXPostBuildEventTool(); + ~VCXPostBuildEventTool(){} +}; + +class VCXPreBuildEventTool : public VCXEventTool +{ +public: + VCXPreBuildEventTool(); + ~VCXPreBuildEventTool(){} +}; + +class VCXPreLinkEventTool : public VCXEventTool +{ +public: + VCXPreLinkEventTool(); + ~VCXPreLinkEventTool(){} +}; + +class VCXConfiguration +{ +public: + // Functions + VCXConfiguration(); + ~VCXConfiguration(){} + + // Variables + triState ATLMinimizesCRunTimeLibraryUsage; + triState BuildBrowserInformation; + QString CharacterSet; + QString ConfigurationType; + QString DeleteExtensionsOnClean; + QString ImportLibrary; + QString IntermediateDirectory; + QString Name; + QString ConfigurationName; + QString OutputDirectory; + QString PrimaryOutput; + QString ProgramDatabase; + triState RegisterOutput; + QString TargetName; + QString UseOfATL; + QString UseOfMfc; + triState WholeProgramOptimization; + + // XML sub-parts + VCXCLCompilerTool compiler; + VCXLibrarianTool librarian; + VCXLinkerTool linker; + VCXMIDLTool idl; + VCXResourceCompilerTool resource; + VCXCustomBuildTool custom; + VCXDeploymentTool deployment; // Not likely to be supported: http://msdn.microsoft.com/en-us/library/sa69he4t.aspx + VCXPostBuildEventTool postBuild; + VCXPreBuildEventTool preBuild; + VCXPreLinkEventTool preLink; +}; + +struct VCXFilterFile +{ + VCXFilterFile() + { excludeFromBuild = false; } + VCXFilterFile(const QString &filename, bool exclude = false ) + { file = filename; excludeFromBuild = exclude; } + VCXFilterFile(const QString &filename, const QString &additional, bool exclude = false ) + { file = filename; excludeFromBuild = exclude; additionalFile = additional; } + bool operator==(const VCXFilterFile &other){ + return file == other.file + && additionalFile == other.additionalFile + && excludeFromBuild == other.excludeFromBuild; + } + + bool excludeFromBuild; + QString file; + QString additionalFile; // For tools like MOC +}; + +class VcxprojGenerator; +class VCXFilter +{ +public: + // Functions + VCXFilter(); + ~VCXFilter(){}; + + void addFile(const QString& filename); + void addFile(const VCXFilterFile& fileInfo); + void addFiles(const QStringList& fileList); + bool addExtraCompiler(const VCXFilterFile &info); + void modifyPCHstage(QString str); + bool outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filename, const QString &filtername, bool fileAllreadyAdded); + + // Variables + QString Name; + QString Filter; + QString Guid; + triState ParseFiles; + VcxprojGenerator* Project; + VCXConfiguration* Config; + QList<VCXFilterFile> Files; + + customBuildCheck CustomBuild; + + bool useCustomBuildTool; + VCXCustomBuildTool CustomBuildTool; + + bool useCompilerTool; + VCXCLCompilerTool CompilerTool; +}; + +typedef QList<VCXFilter> VCXFilterList; +class VCXProjectSingleConfig +{ +public: + enum FilterTypes { + None, + Source, + Header, + Generated, + LexYacc, + Translation, + Resources, + Extras + }; + // Functions + VCXProjectSingleConfig(){}; + ~VCXProjectSingleConfig(){} + + // Variables + QString Name; + QString Version; + QString ProjectGUID; + QString Keyword; + QString SccProjectName; + QString SccLocalPath; + QString PlatformName; + + // XML sub-parts + VCXConfiguration Configuration; + VCXFilter RootFiles; + VCXFilter SourceFiles; + VCXFilter HeaderFiles; + VCXFilter GeneratedFiles; + VCXFilter LexYaccFiles; + VCXFilter TranslationFiles; + VCXFilter FormFiles; + VCXFilter ResourceFiles; + VCXFilterList ExtraCompilersFiles; + + bool flat_files; + + // Accessor for extracompilers + VCXFilter &filterForExtraCompiler(const QString &compilerName); +}; + + + +// Tree & Flat view of files -------------------------------------------------- +class VCXFilter; +class XNode +{ +public: + virtual ~XNode() { } + void addElement(const VCXFilterFile &file) { + addElement(file.file, file); + } + virtual void addElement(const QString &filepath, const VCXFilterFile &allInfo) = 0; + virtual void removeElements()= 0; + virtual void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter) = 0; + virtual bool hasElements() = 0; +}; + +class XTreeNode : public XNode +{ + typedef QMap<QString, XTreeNode*> ChildrenMap; + VCXFilterFile info; + ChildrenMap children; + +public: + virtual ~XTreeNode() { removeElements(); } + + int pathIndex(const QString &filepath) { + int Windex = filepath.indexOf("\\"); + int Uindex = filepath.indexOf("/"); + if (Windex != -1 && Uindex != -1) + return qMin(Windex, Uindex); + else if (Windex != -1) + return Windex; + return Uindex; + } + + void addElement(const QString &filepath, const VCXFilterFile &allInfo){ + QString newNodeName(filepath); + + int index = pathIndex(filepath); + if (index != -1) + newNodeName = filepath.left(index); + + XTreeNode *n = children.value(newNodeName); + if (!n) { + n = new XTreeNode; + n->info = allInfo; + children.insert(newNodeName, n); + } + if (index != -1) + n->addElement(filepath.mid(index+1), allInfo); + } + + void removeElements() { + ChildrenMap::ConstIterator it = children.constBegin(); + ChildrenMap::ConstIterator end = children.constEnd(); + for( ; it != end; it++) { + (*it)->removeElements(); + delete it.value(); + } + children.clear(); + } + + void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &tool, const QString &filter); + bool hasElements() { + return children.size() != 0; + } +}; + +class XFlatNode : public XNode +{ + typedef QMap<QString, VCXFilterFile> ChildrenMapFlat; + ChildrenMapFlat children; + +public: + virtual ~XFlatNode() { removeElements(); } + + int pathIndex(const QString &filepath) { + int Windex = filepath.lastIndexOf("\\"); + int Uindex = filepath.lastIndexOf("/"); + if (Windex != -1 && Uindex != -1) + return qMax(Windex, Uindex); + else if (Windex != -1) + return Windex; + return Uindex; + } + + void addElement(const QString &filepath, const VCXFilterFile &allInfo){ + QString newKey(filepath); + + int index = pathIndex(filepath); + if (index != -1) + newKey = filepath.mid(index+1); + + // Key designed to sort files with same + // name in different paths correctly + children.insert(newKey + "\0" + allInfo.file, allInfo); + } + + void removeElements() { + children.clear(); + } + + void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCXProject &proj, const QString &filter); + bool hasElements() { + return children.size() != 0; + } +}; +// ---------------------------------------------------------------------------- + +class VCXProject +{ +public: + // Variables + QString Name; + QString Version; + QString ProjectGUID; + QString Keyword; + QString SccProjectName; + QString SccLocalPath; + QString PlatformName; + + // Single projects + QList<VCXProjectSingleConfig> SingleProjects; + + // List of all extracompilers + QStringList ExtraCompilers; + + // Functions + void outputFilter(XmlOutput &xml, + XmlOutput &xmlFilter, + const QString &filtername); + + void outputFileConfigs(XmlOutput &xml, + XmlOutput &xmlFilter, + const VCXFilterFile &info, + const QString &filtername); + + void addFilters(XmlOutput &xmlFilter, + const QString &filtername); + +}; + + +XmlOutput &operator<<(XmlOutput &, const VCXCLCompilerTool &); +XmlOutput &operator<<(XmlOutput &, const VCXLinkerTool &); +XmlOutput &operator<<(XmlOutput &, const VCXMIDLTool &); +XmlOutput &operator<<(XmlOutput &, const VCXCustomBuildTool &); +XmlOutput &operator<<(XmlOutput &, const VCXLibrarianTool &); +XmlOutput &operator<<(XmlOutput &, const VCXResourceCompilerTool &); +XmlOutput &operator<<(XmlOutput &, const VCXEventTool &); +XmlOutput &operator<<(XmlOutput &, const VCXDeploymentTool &); +XmlOutput &operator<<(XmlOutput &, const VCXConfiguration &); +XmlOutput &operator<<(XmlOutput &, const VCXProjectSingleConfig &); +XmlOutput &operator<<(XmlOutput &, VCXProject &); + + +QT_END_NAMESPACE + +#endif // MSVC_OBJECTMODEL_H diff --git a/qmake/generators/win32/msvc_dsp.cpp b/qmake/generators/win32/msvc_dsp.cpp deleted file mode 100644 index 9c8dd1db82..0000000000 --- a/qmake/generators/win32/msvc_dsp.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the qmake application of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "msvc_dsp.h" -#include "option.h" - -#include <qdir.h> -#include <qset.h> - -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -DspMakefileGenerator::DspMakefileGenerator() : Win32MakefileGenerator(), init_flag(false) -{ -} - -bool DspMakefileGenerator::writeMakefile(QTextStream &t) -{ - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - /* for now just dump, I need to generated an empty dsp or something.. */ - fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", - var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData()); - return true; - } - - // Generate workspace file - if(project->first("TEMPLATE") == "vcsubdirs") { - if (!project->isActiveConfig("build_pass")) { - debug_msg(1, "Generator: MSVC: Writing workspave file"); - writeSubDirs(t); - } else { - debug_msg(1, "Generator: MSVC: Not writing workspace file for build_pass configs"); - } - return true; - } else if (project->first("TEMPLATE") == "vcapp" || project->first("TEMPLATE") == "vclib") { - if(!project->isActiveConfig("build_pass")) - return writeDspParts(t); - return true; - } - return project->isActiveConfig("build_pass"); -} - -bool DspMakefileGenerator::hasBuiltinCompiler(const QString &filename) const -{ - for (int i = 0; i < Option::cpp_ext.count(); ++i) - if (filename.endsWith(Option::cpp_ext.at(i))) - return true; - for (int i = 0; i < Option::c_ext.count(); ++i) - if (filename.endsWith(Option::c_ext.at(i))) - return true; - return false; -} - -QString DspMakefileGenerator::replaceExtraCompilerVariables(const QString &var, const QStringList &in, const QStringList &out) -{ - QString ret = MakefileGenerator::replaceExtraCompilerVariables(var, in, out); - ret.replace("$(DEFINES)", varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") + - varGlue("DEFINES"," -D"," -D","")); - - QString incpath = this->var("MSVCDSP_INCPATH"); - incpath.replace("/I", "-I"); - ret.replace("$(INCPATH)", incpath); - return ret; -} - - -// if config is part of a multibuild thenthe gule (this) has the correct MSVCDSP_PROJECT -QString DspMakefileGenerator::configName(DspMakefileGenerator * config) -{ - return var("MSVCDSP_PROJECT") + config->var("MSVCDSP_CONFIG_NAME"); -} - -bool DspMakefileGenerator::writeDspHeader(QTextStream &t) -{ - DspMakefileGenerator * config = this; - if (mergedProjects.count()) - config = mergedProjects.at(0); - - t << "# Microsoft Developer Studio Project File - Name=\"" << var("MSVCDSP_PROJECT") << "\" - Package Owner=<4>" << endl; - t << "# Microsoft Developer Studio Generated Build File, Format Version 6.00" << endl; - t << "# ** DO NOT EDIT **" << endl; - t << endl; - t << "# TARGTYPE \"Win32 (x86) " << var("MSVCDSP_TARGETTYPE") << "\" " << var("MSVCDSP_DSPTYPE") << endl; - t << endl; - t << "CFG=\"" << configName(config) << "\"" << endl; - t << "!MESSAGE This is not a valid makefile. To build this project using NMAKE," << endl; - t << "!MESSAGE use the Export Makefile command and run" << endl; - t << "!MESSAGE " << endl; - t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak." << endl; - t << "!MESSAGE " << endl; - t << "!MESSAGE You can specify a configuration when running NMAKE" << endl; - t << "!MESSAGE by defining the macro CFG on the command line. For example:" << endl; - t << "!MESSAGE " << endl; - t << "!MESSAGE NMAKE /f " << escapeFilePath(var("TARGET")) << ".mak CFG=\"" << configName(config) << "\"" << endl; - t << "!MESSAGE " << endl; - t << "!MESSAGE Possible choices for configuration are:" << endl; - t << "!MESSAGE " << endl; - if (mergedProjects.count()) { - for (int i = 0; i < mergedProjects.count(); ++i) { - DspMakefileGenerator * config = mergedProjects.at(i); - t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl; - } - } else { - t << "!MESSAGE \"" << configName(config) << "\" (based on \"Win32 (x86) " << config->var("MSVCDSP_TARGETTYPE") << "\")" << endl; - } - t << "!MESSAGE " << endl; - t << endl; - t << "# Begin Project" << endl; - t << "# PROP AllowPerConfigDependencies 0" << endl; - t << "# PROP Scc_ProjName \"\"" << endl; - t << "# PROP Scc_LocalPath \"\"" << endl; - t << "CPP=" << config->var("QMAKE_CC") << endl; - t << "MTL=" << config->var("QMAKE_IDL") << endl; - t << "RSC=" << config->var("QMAKE_RC") << endl; - t << "BSC32=bscmake.exe" << endl; - - return true; -} - - -bool DspMakefileGenerator::writeDspParts(QTextStream &t) -{ - //bool staticLibTarget = var("MSVCDSP_DSPTYPE") == "0x0104"; - - writeDspHeader(t); - writeDspConfig(t, this); - t << endl; - t << "# Begin Target" << endl; - t << endl; - t << "# Name \"" << configName(this) << "\"" << endl; - t << endl; - - - QStringList listNames = QString("SOURCES|DEF_FILE").split("|"); - QStringList allListNames = listNames; - writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"); - listNames = QStringList("HEADERS"); - allListNames += listNames; - writeFileGroup(t, QStringList("HEADERS"), "Header Files", "h;hpp;hxx;hm;inl"); - listNames = QString("FORMS|INTERFACES|FORMS3").split("|"); - allListNames += listNames; - writeFileGroup(t, listNames, "Form Files", "ui"); - listNames = QStringList("IMAGES"); - allListNames += listNames; - writeFileGroup(t, QStringList("IMAGES"), "Image Files", ""); - listNames = QString("RC_FILE|RESOURCES").split("|"); - allListNames += listNames; - writeFileGroup(t, listNames, "Resources", "rc;qrc"); - listNames = QStringList("TRANSLATIONS"); - allListNames += listNames; - writeFileGroup(t, listNames, "Translations", "ts;xlf"); - listNames = QStringList("LEXSOURCES"); - allListNames += listNames; - writeFileGroup(t, listNames, "Lexables", "l"); - listNames = QStringList("YACCSOURCES"); - allListNames += listNames; - writeFileGroup(t, listNames, "Yaccables", "y"); - listNames = QStringList("TYPELIBS"); - allListNames += listNames; - writeFileGroup(t, listNames, "Type Libraries", "tlb;olb"); - - if (!project->isEmpty("QMAKE_EXTRA_COMPILERS")) { - const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); - for (QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { - const QStringList &inputs = project->values((*it)+".input"); - for (QStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) { - if (!allListNames.contains((*input)) && *input != "UIC3_HEADERS") - writeFileGroup(t, QStringList((*input)), (*input) + " Files", ""); - } - } - } - - project->values("SWAPPED_BUILD_STEPS") = swappedBuildSteps.keys(); - - writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", ""); - - t << "# End Target" << endl; - t << "# End Project" << endl; - return true; -} - -void -DspMakefileGenerator::init() -{ - if(init_flag) - return; - QStringList::Iterator it; - init_flag = true; - - platform = "Win32"; - if(!project->values("QMAKE_PLATFORM").isEmpty()) - platform = varGlue("QMAKE_PLATFORM", "", " ", ""); - - // this should probably not be here, but I'm using it to wrap the .t files - if(project->first("TEMPLATE") == "vcapp") - project->values("QMAKE_APP_FLAG").append("1"); - else if(project->first("TEMPLATE") == "vclib") - project->values("QMAKE_LIB_FLAG").append("1"); - - if(project->values("QMAKESPEC").isEmpty()) - project->values("QMAKESPEC").append(qgetenv("QMAKESPEC")); - - project->values("QMAKE_LIBS") += escapeFilePaths(project->values("LIBS")); - processVars(); - - if(!project->values("VERSION").isEmpty()) { - QString version = project->values("VERSION").first(); - int firstDot = version.indexOf("."); - QString major = version.left(firstDot); - QString minor = version.right(version.length() - firstDot - 1); - minor.replace(".", ""); - project->values("MSVCDSP_LFLAGS").append("/VERSION:" + major + "." + minor); - } - - QString msvcdsp_project; - if(!project->isEmpty("TARGET")) { - project->values("TARGET") = unescapeFilePaths(project->values("TARGET")); - msvcdsp_project = project->first("TARGET"); - } - - MakefileGenerator::init(); - - if(msvcdsp_project.isEmpty()) - msvcdsp_project = Option::output.fileName(); - - msvcdsp_project = msvcdsp_project.right(msvcdsp_project.length() - msvcdsp_project.lastIndexOf("\\") - 1); - int dotFind = msvcdsp_project.lastIndexOf("."); - if(dotFind != -1) - msvcdsp_project = msvcdsp_project.left(dotFind); - msvcdsp_project.replace("-", ""); - - project->values("MSVCDSP_PROJECT").append(msvcdsp_project); - - QStringList &proj = project->values("MSVCDSP_PROJECT"); - - for(QStringList::Iterator it = proj.begin(); it != proj.end(); ++it) - (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); - - if(!project->values("QMAKE_APP_FLAG").isEmpty()) { - if(project->isActiveConfig("console")) { - project->values("MSVCDSP_TARGETTYPE").append("Console Application"); - project->values("MSVCDSP_DSPTYPE").append("0x0103"); - project->values("MSVCDSP_DEFINES").append(" /D \"_CONSOLE\" "); - } else { - project->values("MSVCDSP_TARGETTYPE").append("Application"); - project->values("MSVCDSP_DSPTYPE").append("0x0101"); - project->values("MSVCDSP_DEFINES").append(" /D \"_WINDOWS\" "); - } - } else { - if(project->isActiveConfig("dll")) { - project->values("MSVCDSP_TARGETTYPE").append("Dynamic-Link Library"); - project->values("MSVCDSP_DSPTYPE").append("0x0102"); - project->values("MSVCDSP_DEFINES").append(" /D \"_USRDLL\" "); - } else { - project->values("MSVCDSP_TARGETTYPE").append("Static Library"); - project->values("MSVCDSP_DSPTYPE").append("0x0104"); - project->values("MSVCDSP_DEFINES").append(" /D \"_LIB\" "); - } - } - - project->values("MSVCDSP_LFLAGS") += project->values("QMAKE_LFLAGS"); - - if(!project->values("QMAKE_LIBDIR").isEmpty()) - project->values("MSVCDSP_LFLAGS").append(valGlue( - escapeFilePaths(project->values("QMAKE_LIBDIR")), - "/LIBPATH:"," /LIBPATH:","")); - - project->values("MSVCDSP_DEFINES").append(varGlue("DEFINES","/D ","" " /D ","")); - project->values("MSVCDSP_DEFINES").append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ","")); - project->values("MSVCDSP_DEFINES").append(" /D \"WIN32\" "); - - QStringList &libs = project->values("QMAKE_LIBS"); - for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) { - project->values("MSVCDSP_LIBS").append(" " + escapeFilePath(*libit)); - } - - QStringList &incs = project->values("INCLUDEPATH"); - for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { - QString inc = (*incit); - project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(inc)); - } - project->values("MSVCDSP_INCPATH").append("/I" + escapeFilePath(specdir())); - - QString dest; - QString preLinkStep; - QString postLinkStep; - QString copyDllStep; - - if(!project->values("QMAKE_PRE_LINK").isEmpty()) - preLinkStep += var("QMAKE_PRE_LINK"); - - if(!project->values("QMAKE_POST_LINK").isEmpty()) - postLinkStep += var("QMAKE_POST_LINK"); - - // don't destroy the target, it is used by prl writer. - if(!project->values("DESTDIR").isEmpty()) { - dest = project->first("DESTDIR"); - project->values("DESTDIR").first() = dest; - dest = project->values("TARGET").first() + project->first("TARGET_EXT"); - dest.prepend(project->first("DESTDIR")); - Option::fixPathToTargetOS(dest); - dest = escapeFilePath(dest); - - project->values("MSVCDSP_TARGET").append( - QString("/out:") + dest); - if(project->isActiveConfig("dll")) { - QString imp = dest; - imp.replace(".dll", ".lib"); - project->values("MSVCDSP_TARGET").append(QString(" /implib:") + escapeFilePath(imp)); - } - } - - if(project->isActiveConfig("dll") && !project->values("DLLDESTDIR").isEmpty()) { - QStringList dlldirs = project->values("DLLDESTDIR"); - if(dlldirs.count()) - copyDllStep += "\t"; - for(QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) { - copyDllStep += "copy \"$(TargetPath)\" " + escapeFilePath(Option::fixPathToTargetOS(*dlldir)) + "\t"; - } - } - - if(!preLinkStep.isEmpty()) { - project->values("MSVCDSP_PRE_LINK").append( - "# Begin Special Build Tool\n" - "SOURCE=$(InputPath)\n" - "PreLink_Desc=Post Build Step\n" - "PreLink_Cmds=" + preLinkStep + "\n" - "# End Special Build Tool\n"); - } - - if(!postLinkStep.isEmpty() || !copyDllStep.isEmpty()) { - project->values("MSVCDSP_POST_LINK").append( - "# Begin Special Build Tool\n" - "SOURCE=$(InputPath)\n" - "PostBuild_Desc=Post Build Step\n" - "PostBuild_Cmds=" + postLinkStep + copyDllStep + "\n" - "# End Special Build Tool\n"); - } - - QStringList &formList = project->values("FORMS"); - for(QStringList::ConstIterator hit = formList.begin(); hit != formList.end(); ++hit) { - if(exists(*hit + ".h")) - project->values("SOURCES").append(*hit + ".h"); - } - QStringList &form3List = project->values("FORMS3"); - for(QStringList::ConstIterator hit = form3List.begin(); hit != form3List.end(); ++hit) { - if(exists(*hit + ".h")) - project->values("SOURCES").append(*hit + ".h"); - } - - project->values("QMAKE_INTERNAL_PRL_LIBS") << "MSVCDSP_LIBS"; - - // Move some files around //### is this compat? - if (!project->values("IMAGES").isEmpty()) { - QString imageFactory(project->first("QMAKE_IMAGE_COLLECTION")); - project->values("GENERATED_SOURCES") += imageFactory; - project->values("SOURCES").removeAll(imageFactory); - } - - // Setup PCH variables - precompH = project->first("PRECOMPILED_HEADER"); - namePCH = fileInfo(precompH).fileName(); - usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header"); - if (usePCH) { - // Created files - precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext; - precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch"; - - // Add PRECOMPILED_HEADER to HEADERS - if (!project->values("HEADERS").contains(precompH)) - project->values("HEADERS") += precompH; - // Add precompile compiler options - project->values("PRECOMPILED_FLAGS") = QStringList("/Fp" + precompPch + " /Yu" + escapeFilePath(namePCH) + " /FI" + escapeFilePath(namePCH) + " "); - // Return to variable pool - project->values("PRECOMPILED_OBJECT") = QStringList(precompObj); - project->values("PRECOMPILED_PCH") = QStringList(precompPch); - } - - QString buildName; - if (!var("BUILD_NAME").isEmpty()) - buildName = var("BUILD_NAME"); - else if (project->isActiveConfig("debug")) - buildName = "Debug"; - else - buildName = "Release"; - - project->values("MSVCDSP_CONFIG_NAME") = QStringList(" - " + platform + " " + buildName); -} - -void DspMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) -{ - if(var == "QMAKE_PRL_DEFINES") { - QStringList &out = project->values("MSVCDSP_DEFINES"); - for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { - if(out.indexOf((*it)) == -1) - out.append((" /D \"" + *it + "\"")); - } - } else { - MakefileGenerator::processPrlVariable(var, l); - } -} - -bool DspMakefileGenerator::openOutput(QFile &file, const QString &build) const -{ - QString outdir; - if(!file.fileName().isEmpty()) { - if(QDir::isRelativePath(file.fileName())) - file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run - QFileInfo fi(fileInfo(file.fileName())); - if(fi.isDir()) - outdir = file.fileName() + QDir::separator(); - } - - if(!outdir.isEmpty() || file.fileName().isEmpty()) { - QString ext = project->first("DSP_EXTENSION"); - if(project->first("TEMPLATE") == "vcsubdirs") { - if (!project->first("DSW_EXTENSION").isEmpty()) - ext = project->first("DSW_EXTENSION"); - else - ext = ".dsw"; - } - QString outputName = unescapeFilePath(project->first("QMAKE_DSP_PROJECT_NAME")); - if (!project->first("MAKEFILE").isEmpty()) - outputName = unescapeFilePath(project->first("MAKEFILE")); - if (outputName.isEmpty()) - outputName = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); - file.setFileName(outdir + outputName + ext); - } - - if(QDir::isRelativePath(file.fileName())) { - QString ofile = Option::fixPathToLocalOS(file.fileName()); - int slashfind = ofile.lastIndexOf(Option::dir_sep); - if(slashfind == -1) { - ofile = ofile.replace(QRegExp("-"), "_"); - } else { - int hypenfind = ofile.indexOf('-', slashfind); - while (hypenfind != -1 && slashfind < hypenfind) { - ofile = ofile.replace(hypenfind, 1, "_"); - hypenfind = ofile.indexOf('-', hypenfind + 1); - } - } - file.setFileName(Option::fixPathToLocalOS(qmake_getpwd() + Option::dir_sep + ofile)); - } - return Win32MakefileGenerator::openOutput(file, build); -} - -bool DspMakefileGenerator::mergeBuildProject(MakefileGenerator *other) -{ - - mergedProjects.prepend(static_cast<DspMakefileGenerator*>(other)); - return true; -} - -bool DspMakefileGenerator::writeProjectMakefile() -{ - bool ret = true; - - QTextStream t(&Option::output); - // Check if all requirements are fulfilled - if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { - fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", - var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData()); - return true; - } - - // Generate project file - if(project->first("TEMPLATE") == "vcapp" || - project->first("TEMPLATE") == "vclib") { - if (!mergedProjects.count()) { - warn_msg(WarnLogic, "Generator: MSVC DSP: no single configuration created, cannot output project!"); - return false; - } - debug_msg(1, "Generator: MSVC 6: Writing project file"); - - writeDspHeader(t); - for (int i = 0; i < mergedProjects.count(); ++i) { - DspMakefileGenerator* config = mergedProjects.at(i); - t << endl; - if (i == 0) - t << "!IF"; - else - t << "!ELSEIF"; - t << " \"$(CFG)\" == \"" << configName(config) << "\"" << endl; - t << endl; - writeDspConfig(t, config); - } - t << endl; - t << "!ENDIF " << endl; - t << endl; - t << "# Begin Target" << endl; - t << endl; - for (int i = 0; i < mergedProjects.count(); ++i) - t << "# Name \"" << configName(mergedProjects.at(i)) << "\"" << endl; - t << endl; - - QMap< QString, QSet<QString> > files; - - // merge source files - for (int i = 0; i < mergedProjects.count(); ++i) { - - DspMakefileGenerator* config = mergedProjects.at(i); - - files["DEF_FILE"] += config->project->values("DEF_FILE").toSet(); - files["SOURCES"] += config->project->values("SOURCES").toSet(); - files["HEADERS"] += config->project->values("HEADERS").toSet(); - files["INTERFACES"] += config->project->values("INTERFACES").toSet(); - files["FORMS"] += config->project->values("FORMS").toSet(); - files["FORMS"] += config->project->values("FORMS3").toSet(); - files["IMAGES"] += config->project->values("IMAGES").toSet(); - files["RC_FILE"] += config->project->values("RC_FILE").toSet(); - files["RESOURCES"] += config->project->values("RESOURCES").toSet(); - files["TRANSLATIONS"] += config->project->values("TRANSLATIONS").toSet(); - files["LEXSOURCES"] += config->project->values("LEXSOURCES").toSet(); - files["YACCSOURCES"] += config->project->values("YACCSOURCES").toSet(); - files["TYPELIBS"] += config->project->values("TYPELIBS").toSet(); - - if (!config->project->isEmpty("QMAKE_EXTRA_COMPILERS")) { - const QStringList &quc = config->project->values("QMAKE_EXTRA_COMPILERS"); - for (QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { - const QStringList &inputs = project->values((*it)+".input"); - for (QStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) { - if (*input != "UIC3_HEADERS") - files[(*input)] += config->project->values((*input)).toSet(); - } - } - } - } - - QStringList keys = files.keys(); - for (int k = 0; k < keys.size(); ++k) - project->values(keys.at(k)) = QList<QString>::fromSet(files[keys.at(k)]); - - QStringList listNames = QString("SOURCES|DEF_FILE").split("|"); - QStringList allListNames = listNames; - writeFileGroup(t, listNames, "Source Files", "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"); - listNames = QStringList("HEADERS"); - allListNames += listNames; - writeFileGroup(t, listNames, "Header Files", "h;hpp;hxx;hm;inl"); - listNames = QString("FORMS|INTERFACES|FORMS3").split("|"); - allListNames += listNames; - writeFileGroup(t, listNames, "Form Files", "ui"); - listNames = QStringList("IMAGES"); - allListNames += listNames; - writeFileGroup(t, listNames, "Image Files", ""); - listNames = QString("RC_FILE|RESOURCES").split("|"); - allListNames += listNames; - writeFileGroup(t, listNames, "Resources", "rc;qrc"); - listNames = QStringList("TRANSLATIONS"); - allListNames += listNames; - writeFileGroup(t, listNames, "Translations", "ts;xlf"); - listNames = QStringList("LEXSOURCES"); - allListNames += listNames; - writeFileGroup(t, listNames, "Lexables", "l"); - listNames = QStringList("YACCSOURCES"); - allListNames += listNames; - writeFileGroup(t, listNames, "Yaccables", "y"); - listNames = QStringList("TYPELIBS"); - allListNames += listNames; - writeFileGroup(t, listNames, "Type Libraries", "tlb;olb"); - - for (int l = 0; l < allListNames.size(); ++l) - keys.removeAll(allListNames.at(l)); - - for (int k = 0; k < keys.size(); ++k) - writeFileGroup(t, QStringList(keys.at(k)), keys.at(k) + " Files", ""); - - // done last as generated may have changed when creating build rules for the above - for (int i = 0; i < mergedProjects.count(); ++i) { - - DspMakefileGenerator* config = mergedProjects.at(i); - - config->project->values("SWAPPED_BUILD_STEPS") = config->swappedBuildSteps.keys(); - files["SWAPPED_BUILD_STEPS"] += config->project->values("SWAPPED_BUILD_STEPS").toSet(); - - files["GENERATED_SOURCES"] += config->project->values("GENERATED_SOURCES").toSet(); - files["GENERATED_FILES"] += config->project->values("GENERATED_FILES").toSet(); - } - - project->values("SWAPPED_BUILD_STEPS") = QList<QString>::fromSet(files["SWAPPED_BUILD_STEPS"]); - project->values("GENERATED_SOURCES") = QList<QString>::fromSet(files["GENERATED_SOURCES"]); - project->values("GENERATED_FILES") = QList<QString>::fromSet(files["GENERATED_FILES"]); - - writeFileGroup(t, QString("GENERATED_SOURCES|GENERATED_FILES|SWAPPED_BUILD_STEPS").split("|"), "Generated", ""); - t << endl; - t << "# End Target" << endl; - t << "# End Project" << endl; - }else if(project->first("TEMPLATE") == "vcsubdirs") { - ret = writeMakefile(t); - } - - return ret; -} - -const char _dswHeader60[] = "Microsoft Developer Studio Workspace File, Format Version 6.00\n"; -const char _dswWarning[] = "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n"; -const char _dswDevider[] = "###############################################################################\n"; -const char _dswProjectName[] = "Project: \"%1\"=%2 - Package Owner=<4>\n"; // %1 = project name, %2 = project path -const char _dswPackage5Start[] = "Package=<5>\n{{{\n"; -const char _dswPackage5Stop[] = "}}}\n"; -const char _dswPackage4Start[] = "Package=<4>\n{{{\n"; -const char _dswPackage4Stop[] = "}}}\n"; -const char _dswProjectDep[] = " Begin Project Dependency\n Project_Dep_Name %1\n End Project Dependency\n"; // %1 = project name -const char _dswGlobal[] = "Global:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n"; - - -struct WorkspaceDepend { - QString dspProjectFile, orig_target, target; - QStringList dependencies; -}; - -void DspMakefileGenerator::writeSubDirs(QTextStream &t) -{ - // Output headers - t << _dswHeader60; - t << _dswWarning; - t << endl; - - QHash<QString, WorkspaceDepend*> workspace_depends; - QList<WorkspaceDepend*> workspace_cleanup; - QStringList subdirs = project->values("SUBDIRS"); - QString oldpwd = qmake_getpwd(); - - // Make sure that all temp projects are configured - // for release so that the depends are created - // without the debug <lib>dxxx.lib name mangling - QStringList old_after_vars = Option::after_user_vars; - Option::after_user_vars.append("CONFIG+=release"); - - for(int i = 0; i < subdirs.size(); ++i) { - QString tmp = subdirs.at(i); - if(!project->isEmpty(tmp + ".file")) { - if(!project->isEmpty(tmp + ".subdir")) - warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s", - tmp.toLatin1().constData()); - tmp = project->first(tmp + ".file"); - } else if(!project->isEmpty(tmp + ".subdir")) { - tmp = project->first(tmp + ".subdir"); - } - - QFileInfo fi(fileInfo(Option::fixPathToLocalOS(tmp, true))); - if(fi.exists()) { - if(fi.isDir()) { - QString profile = tmp; - if(!profile.endsWith(Option::dir_sep)) - profile += Option::dir_sep; - profile += fi.baseName() + Option::pro_ext; - subdirs.append(profile); - } else { - QMakeProject tmp_proj; - QString dir = fi.path(), fn = fi.fileName(); - if(!dir.isEmpty()) { - if(!qmake_setpwd(dir)) - fprintf(stderr, "Cannot find directory: %s\n", dir.toLatin1().constData()); - } - if(tmp_proj.read(fn)) { - // Check if all requirements are fulfilled - if(!tmp_proj.variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { - fprintf(stderr, "Project file(%s) not added to Workspace because all requirements not met:\n\t%s\n", - fn.toLatin1().constData(), tmp_proj.values("QMAKE_FAILED_REQUIREMENTS").join(" ").toLatin1().constData()); - continue; - } - if(tmp_proj.first("TEMPLATE") == "vcsubdirs") { - QStringList tmp_proj_subdirs = tmp_proj.variables()["SUBDIRS"]; - for(int x = 0; x < tmp_proj_subdirs.size(); ++x) { - QString tmpdir = tmp_proj_subdirs.at(x); - if(!tmp_proj.isEmpty(tmpdir + ".file")) { - if(!tmp_proj.isEmpty(tmpdir + ".subdir")) - warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s", - tmpdir.toLatin1().constData()); - tmpdir = tmp_proj.first(tmpdir + ".file"); - } else if(!tmp_proj.isEmpty(tmpdir + ".subdir")) { - tmpdir = tmp_proj.first(tmpdir + ".subdir"); - } - subdirs += fileFixify(tmpdir); - } - } else if(tmp_proj.first("TEMPLATE") == "vcapp" || tmp_proj.first("TEMPLATE") == "vclib") { - // Initialize a 'fake' project to get the correct variables - // and to be able to extract all the dependencies - DspMakefileGenerator tmp_dsp; - tmp_dsp.setNoIO(true); - tmp_dsp.setProjectFile(&tmp_proj); - if(Option::debug_level) { - QMap<QString, QStringList> &vars = tmp_proj.variables(); - for(QMap<QString, QStringList>::Iterator it = vars.begin(); - it != vars.end(); ++it) { - if(it.key().left(1) != "." && !it.value().isEmpty()) - debug_msg(1, "%s: %s === %s", fn.toLatin1().constData(), it.key().toLatin1().constData(), - it.value().join(" :: ").toLatin1().constData()); - } - } - - // We assume project filename is [QMAKE_ORIG_TARGET].vcproj - QString dsp = unescapeFilePath(tmp_dsp.project->first("MSVCDSP_PROJECT") + project->first("DSP_EXTENSION")); - - // If file doesn't exsist, then maybe the users configuration - // doesn't allow it to be created. Skip to next... - if(!exists(qmake_getpwd() + Option::dir_sep + dsp)) { - warn_msg(WarnLogic, "Ignored (not found) '%s'", QString(qmake_getpwd() + Option::dir_sep + dsp).toLatin1().constData()); - goto nextfile; // # Dirty! - } - - WorkspaceDepend *newDep = new WorkspaceDepend; - newDep->dspProjectFile = fileFixify(dsp); - newDep->orig_target = unescapeFilePath(tmp_proj.first("QMAKE_ORIG_TARGET")); - newDep->target = tmp_proj.first("MSVCDSP_PROJECT").section(Option::dir_sep, -1) + tmp_proj.first("TARGET_EXT"); - - // We want to store it as the .lib name. - if(newDep->target.endsWith(".dll")) - newDep->target = newDep->target.left(newDep->target.length()-3) + "lib"; - - // All projects having mocable sourcefiles are dependent on moc.exe - if(tmp_proj.variables()["CONFIG"].contains("moc")) - newDep->dependencies << "moc.exe"; - - // All extra compilers which has valid input are considered dependencies - const QStringList &quc = tmp_proj.variables()["QMAKE_EXTRA_COMPILERS"]; - for(QStringList::ConstIterator it = quc.constBegin(); it != quc.constEnd(); ++it) { - const QStringList &invar = tmp_proj.variables().value((*it) + ".input"); - for(QStringList::ConstIterator iit = invar.constBegin(); iit != invar.constEnd(); ++iit) { - const QStringList fileList = tmp_proj.variables().value(*iit); - if (!fileList.isEmpty()) { - QString dep = tmp_proj.first((*it) + ".commands").section('/', -1).section('\\', -1); - if (!newDep->dependencies.contains(dep)) - newDep->dependencies << dep; - } - } - } - - // Add all unknown libs to the deps - QStringList where("QMAKE_LIBS"); - if(!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS")) - where = tmp_proj.variables()["QMAKE_INTERNAL_PRL_LIBS"]; - - for(QStringList::iterator wit = where.begin(); - wit != where.end(); ++wit) { - QStringList &l = tmp_proj.variables()[(*wit)]; - for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - QString opt = (*it).trimmed(); - if(!opt.startsWith("/") && // Not a switch - opt != newDep->target && // Not self - opt != "opengl32.lib" && // We don't care about these libs - opt != "glu32.lib" && // to make depgen alittle faster - opt != "kernel32.lib" && - opt != "user32.lib" && - opt != "gdi32.lib" && - opt != "comdlg32.lib" && - opt != "advapi32.lib" && - opt != "shell32.lib" && - opt != "ole32.lib" && - opt != "oleaut32.lib" && - opt != "uuid.lib" && - opt != "imm32.lib" && - opt != "winmm.lib" && - opt != "wsock32.lib" && - opt != "ws2_32.lib" && - opt != "winspool.lib" && - opt != "delayimp.lib") - { - newDep->dependencies << opt.section(Option::dir_sep, -1); - } - } - } - workspace_cleanup.append(newDep); - workspace_depends.insert(newDep->target, newDep); - - debug_msg(1, "Generator: MSVC: Added project (name:'%s' path:'%s' deps:'%s')", - qPrintable(newDep->target) , qPrintable(newDep->dspProjectFile), - qPrintable(newDep->dependencies.join(";"))); - } - } -nextfile: - qmake_setpwd(oldpwd); - } - } - } - - // Restore previous after_user_var options - Option::after_user_vars = old_after_vars; - - // Output all projects - QString dswProjectName = QLatin1String(_dswProjectName); - QString dswProjectDep = QLatin1String(_dswProjectDep); - for(QList<WorkspaceDepend*>::Iterator it = workspace_cleanup.begin(); it != workspace_cleanup.end(); ++it) { - t << _dswDevider; - t << endl; - t << dswProjectName.arg((*it)->orig_target).arg((*it)->dspProjectFile); - t << endl; - t << _dswPackage5Start; - t << _dswPackage5Stop; - t << endl; - t << _dswPackage4Start; - - // Output project dependencies - for(QStringList::iterator dit = (*it)->dependencies.begin(); dit != (*it)->dependencies.end(); ++dit) { - if(WorkspaceDepend *vc = workspace_depends[*dit]) - t << dswProjectDep.arg(vc->orig_target); - } - - t << _dswPackage4Stop; - } - - // Output global part - t << _dswDevider << endl; - t << _dswGlobal; - t << _dswDevider; - t << endl << endl; -} - -class FolderGroup -{ -public: - QString name; - QString filter; - QMap<QString, FolderGroup *> subFolders; - QMap<QString, QString> files; - - void insertStructured(const QString &file, const QString &fileListName) - { - QStringList path = QFileInfo(file).path().split("/"); - if (!path.isEmpty() && path.at(0) == ".") - path.takeAt(0); - FolderGroup *currentFolder = this; - for (int i = 0; i < path.size(); i++) { - if (currentFolder->subFolders.contains(path.at(i))) { - currentFolder = currentFolder->subFolders.value(path.at(i)); - } else { - FolderGroup *newFolder = new FolderGroup; - newFolder->name = path.at(i); - currentFolder->subFolders.insert(path.at(i), newFolder); - currentFolder = newFolder; - } - } - currentFolder->files.insert(file, fileListName); - } - - void insertFlat(const QString &file, const QString &fileListName) - { - files.insert(file, fileListName); - } - - ~FolderGroup() - { - qDeleteAll(subFolders.values()); - } -}; - -bool DspMakefileGenerator::writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter) -{ - FolderGroup root; - root.name = group; - root.filter = filter; - - for (int i = 0; i < listNames.count(); ++i) { - QStringList list = project->values(listNames.at(i)); - for (int j = 0; j < list.count(); ++j) { - const QString name = list.at(j); - if (name.isEmpty()) - continue; - if (project->isActiveConfig("flat")) - root.insertFlat(name, listNames.at(i)); - else - root.insertStructured(name, listNames.at(i)); - } - } - - if (root.files.isEmpty() && root.subFolders.isEmpty()) - return true; - - writeSubFileGroup(t, &root); - - return true; -} - -void DspMakefileGenerator::writeSubFileGroup(QTextStream &t, FolderGroup *folder) -{ - t << "# Begin Group \"" << folder->name << "\"" << endl; - t << "# PROP Default_Filter \"" << folder->filter << "\"" << endl; - QMap<QString, FolderGroup *>::const_iterator folderIt = folder->subFolders.begin(); - while (folderIt != folder->subFolders.end()) { - writeSubFileGroup(t, folderIt.value()); - ++folderIt; - } - QMap<QString, QString>::const_iterator it = folder->files.begin(); - while (it != folder->files.end()) { - t << "# Begin Source File" << endl; - t << "SOURCE=" << escapeFilePath(it.key()) << endl; - writeBuildstepForFile(t, it.key(), it.value()); - t << "# End Source File" << endl; - t << endl; - ++it; - } - t << "# End Group" << endl; - t << endl; -} - -bool DspMakefileGenerator::writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName) -{ - - if (!mergedProjects.count()) { - t << writeBuildstepForFileForConfig(file, listName, this); - return true; - } - - //only add special build rules when needed - - QStringList specialBuilds; - int i = 0; - for (i = 0; i < mergedProjects.count(); ++i) - specialBuilds += writeBuildstepForFileForConfig(file, listName, mergedProjects.at(i)); - - // no special build just return - if (specialBuilds.join("").isEmpty()) - return true; - - for (i = 0; i < mergedProjects.count(); ++i) { - if (i == 0) - t << "!IF"; - else - t << "!ELSEIF"; - t << " \"$(CFG)\" == \"" << configName(mergedProjects.at(i)) << "\"" << endl; - t << endl; - t << specialBuilds.at(i); - t << endl; - } - - t << "!ENDIF" << endl; - - return true; -} - -bool DspMakefileGenerator::writeDspConfig(QTextStream &t, DspMakefileGenerator *config) -{ - - bool isDebug = config->project->isActiveConfig("debug"); - bool staticLibTarget = config->var("MSVCDSP_DSPTYPE") == "0x0104"; - - QString outDir = Option::fixPathToTargetOS(config->project->first("DESTDIR")); - while (outDir.endsWith(Option::dir_sep)) - outDir.chop(1); - outDir = config->escapeFilePath(outDir); - - QString intDir = config->project->first("OBJECTS_DIR"); - while (intDir.endsWith(Option::dir_sep)) - intDir.chop(1); - intDir = config->escapeFilePath(intDir); - - t << "# PROP BASE Use_MFC 0" << endl; - t << "# PROP BASE Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl; - t << "# PROP BASE Output_Dir " << outDir << endl; - t << "# PROP BASE Intermediate_Dir " << intDir << endl; - t << "# PROP BASE Target_Dir \"\"" << endl; - t << "# PROP Use_MFC 0" << endl; - t << "# PROP Use_Debug_Libraries " << (isDebug ? "1" : "0") << endl; - - t << "# PROP Output_Dir " << outDir << endl; - t << "# PROP Intermediate_Dir " << intDir << endl; - if (config->project->isActiveConfig("dll") || config->project->isActiveConfig("plugin")) - t << "# PROP Ignore_Export_Lib 1" << endl; - t << "# PROP Target_Dir \"\"" << endl; - t << "# ADD CPP " << config->var("MSVCDSP_INCPATH") << " /c /FD " << config->var("QMAKE_CXXFLAGS") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("PRECOMPILED_FLAGS") << endl; - t << "# ADD MTL /nologo /mktyplib203 /win32 /D " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl; - t << "# ADD RSC /l 0x409 /d " << (isDebug ? "\"_DEBUG\"" : "\"NDEBUG\"") << endl; - t << "# ADD BSC32 /nologo" << endl; - if (staticLibTarget) { - t << "LIB32=" << config->var("QMAKE_LIB") << endl; - t << "# ADD LIB32 " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl; - } else { - t << "LINK32=" << config->var("QMAKE_LINK") << endl; - t << "# ADD LINK32 " << config->var("MSVCDSP_LFLAGS") << " " << config->var("MSVCDSP_LIBS") << " " << config->var("MSVCDSP_TARGET") << " " << config->var("PRECOMPILED_OBJECT") << endl; - } - - if (!config->project->values("MSVCDSP_PRE_LINK").isEmpty()) - t << config->project->values("MSVCDSP_PRE_LINK").first(); - - if (!config->project->values("MSVCDSP_POST_LINK").isEmpty()) - t << config->project->values("MSVCDSP_POST_LINK").first(); - - return true; -} - -QString DspMakefileGenerator::writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config) -{ - QString ret; - QTextStream t(&ret); - - // exclude from build - if (!config->project->values(listName).contains(file)) { - t << "# PROP Exclude_From_Build 1" << endl; - return ret; - } - - if (config->usePCH) { - bool c_file = false; - for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) { - if (file.endsWith(*it)) { - c_file = true; - break; - } - } - if(c_file) { - t << "# SUBTRACT CPP /FI" << config->escapeFilePath(config->namePCH) << " /Yu" << config->escapeFilePath(config->namePCH) << " /Fp" << endl; - return ret; - } else if (config->precompH.endsWith(file)) { - // ### dependency list quickly becomes too long for VS to grok... - t << "USERDEP_" << file << "=" << config->valGlue(config->escapeFilePaths(config->findDependencies(config->precompH)), "", "\t", "") << endl; - t << endl; - t << "# Begin Custom Build - Creating precompiled header from " << file << "..." << endl; - t << "InputPath=.\\" << config->escapeFilePath(file) << endl << endl; - t << config->precompPch + ": $(SOURCE) \"$(IntDir)\" \"$(OUTDIR)\"" << endl; - t << "\t" << config->var("QMAKE_CC") << " /TP /W3 /FD /c /Yc /Fp" << config->precompPch << " /Fo" << config->precompObj << " /Fd\"$(IntDir)\\\\\" " << file << " "; - t << config->var("MSVCDSP_INCPATH") << " " << config->var("MSVCDSP_DEFINES") << " " << config->var("QMAKE_CXXFLAGS") << endl; - t << "# End Custom Build" << endl << endl; - return ret; - } - } - - QString fileBase = QFileInfo(file).completeBaseName(); - - bool hasBuiltin = config->hasBuiltinCompiler(file); - BuildStep allSteps; - - if (!config->swappedBuildSteps.contains(file)) { - QStringList compilers = config->project->values("QMAKE_EXTRA_COMPILERS"); - for (int i = 0; i < compilers.count(); ++i) { - QString compiler = compilers.at(i); - if (config->project->values(compiler + ".input").isEmpty()) - continue; - QString input = config->project->values(compiler + ".input").first(); - QStringList inputList = config->project->values(input); - if (!inputList.contains(file)) - continue; - - QStringList compilerCommands = config->project->values(compiler + ".commands"); - QStringList compilerOutput = config->project->values(compiler + ".output"); - if (compilerCommands.isEmpty() || compilerOutput.isEmpty()) - continue; - - QStringList compilerName = config->project->values(compiler + ".name"); - if (compilerName.isEmpty()) - compilerName << compiler; - QStringList compilerDepends = config->project->values(compiler + ".depends"); - QString compilerDependsCommand = config->project->values(compiler + ".depend_command").join(" "); - if (!compilerDependsCommand.isEmpty()) { - if(!config->canExecute(compilerDependsCommand)) - compilerDependsCommand = QString(); - } - QStringList compilerConfig = config->project->values(compiler + ".CONFIG"); - - if (!config->verifyExtraCompiler(compiler, file)) - continue; - - bool combineAll = compilerConfig.contains("combine"); - if (combineAll && inputList.first() != file) - continue; - - QString fileIn("$(InputPath)"); - - if (combineAll && !inputList.isEmpty()) { - fileIn = inputList.join(" "); - compilerDepends += inputList; - } - - QString fileOut = compilerOutput.first(); - QString fileOutBase = QFileInfo(fileOut).completeBaseName(); - fileOut.replace("${QMAKE_FILE_IN}", fileIn); - fileOut.replace("${QMAKE_FILE_BASE}", fileBase); - fileOut.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase); - fileOut.replace('/', '\\'); - - BuildStep step; - for (int i2 = 0; i2 < compilerDepends.count(); ++i2) { - QString dependency = compilerDepends.at(i2); - dependency.replace("${QMAKE_FILE_IN}", fileIn); - dependency.replace("${QMAKE_FILE_BASE}", fileBase); - dependency.replace("${QMAKE_FILE_OUT_BASE}", fileOutBase); - dependency.replace('/', '\\'); - if (!step.deps.contains(dependency, Qt::CaseInsensitive)) - step.deps << dependency; - } - // depends command - if (!compilerDependsCommand.isEmpty() && config->doDepends()) { - char buff[256]; - QString dep_cmd = config->replaceExtraCompilerVariables(compilerDependsCommand, file, - fileOut); - dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false); - if(config->canExecute(dep_cmd)) { - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { - QString indeps; - while(!feof(proc)) { - int read_in = (int)fread(buff, 1, 255, proc); - if(!read_in) - break; - indeps += QByteArray(buff, read_in); - } - QT_PCLOSE(proc); - if(!indeps.isEmpty()) - step.deps += config->fileFixify(indeps.replace('\n', ' ').simplified().split(' ')); - } - } - } - - - QString mappedFile; - if (hasBuiltin) { - mappedFile = fileOut; - fileOut = fileIn; - fileIn = file; - } - - step.buildStep += " \\\n\t"; - QString command(compilerCommands.join(" ")); - // Replace any newlines with proper line-continuance - command.replace("\n", " \\\n\t"); - // Might be a macro, and not a valid filename, so the replaceExtraCompilerVariables() would eat it - command.replace("${QMAKE_FILE_IN}", config->escapeFilePath(fileIn)); - command.replace("${QMAKE_FILE_BASE}", config->escapeFilePath(fileBase)); - command.replace("${QMAKE_FILE_OUT_BASE}", config->escapeFilePath(fileOutBase)); - command.replace("${QMAKE_FILE_OUT}", config->escapeFilePath(fileOut)); - - command = config->replaceExtraCompilerVariables(command, fileIn, fileOut); - - step.buildName = compilerName.first(); - step.buildStep += command; - step.buildOutputs += fileOut; - - if (hasBuiltin) { - step.deps << fileIn; - config->swappedBuildSteps[mappedFile] = step; - } else { - allSteps << step; - } - } - } else { - allSteps << config->swappedBuildSteps.value(file); - } - - if (allSteps.buildStep.isEmpty()) - return ret; - - int i; - QStringList dependencyList; - // remove dependencies that are also output - for (i = 0; i < 1; ++i) { - QStringList buildOutput(allSteps.buildOutputs.at(i)); - - for (int i2 = 0; i2 < allSteps.deps.count(); ++i2) { - QString dependency = allSteps.deps.at(i2); - if (!buildOutput.contains(dependency) && !dependencyList.contains(dependency)) - dependencyList << dependency; - } - } - QString allDependencies = config->valGlue(dependencyList, "", "\t", ""); - t << "USERDEP_" << file << "=" << allDependencies << endl; - t << "# PROP Ignore_Default_Tool 1" << endl; - t << "# Begin Custom Build - Running " << allSteps.buildName << " on " << file << endl; - t << "InputPath=" << file << endl; - t << "BuildCmds= " << allSteps.buildStep << endl; - for (i = 0; i < allSteps.buildOutputs.count(); ++i) { - t << config->escapeFilePath(allSteps.buildOutputs.at(i)) - << " : $(SOURCE) $(INTDIR) $(OUTDIR)\n\t$(BuildCmds)\n"; - } - t << endl; - t << "# End Custom Build" << endl; - - return ret; -} - -QT_END_NAMESPACE diff --git a/qmake/generators/win32/msvc_dsp.h b/qmake/generators/win32/msvc_dsp.h deleted file mode 100644 index f3e2435622..0000000000 --- a/qmake/generators/win32/msvc_dsp.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the qmake application of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MSVC_DSP_H -#define MSVC_DSP_H - -#include "winmakefile.h" - -QT_BEGIN_NAMESPACE - -class FolderGroup; - -class DspMakefileGenerator : public Win32MakefileGenerator -{ - bool init_flag; - bool writeDspHeader(QTextStream &); - bool writeDspParts(QTextStream &); - bool writeFileGroup(QTextStream &t, const QStringList &listNames, const QString &group, const QString &filter); - void writeSubFileGroup(QTextStream &t, FolderGroup *folder); - bool writeBuildstepForFile(QTextStream &t, const QString &file, const QString &listName); - static bool writeDspConfig(QTextStream &t, DspMakefileGenerator *config); - static QString writeBuildstepForFileForConfig(const QString &file, const QString &listName, DspMakefileGenerator *config); - QString configName(DspMakefileGenerator * config); - - bool writeMakefile(QTextStream &); - bool writeProjectMakefile(); - void writeSubDirs(QTextStream &t); - void init(); - -public: - DspMakefileGenerator(); - ~DspMakefileGenerator(); - - bool openOutput(QFile &file, const QString &build) const; - bool hasBuiltinCompiler(const QString &filename) const; - -protected: - virtual bool doDepends() const { return false; } //never necesary - virtual void processSources() { filterIncludedFiles("SOURCES"); filterIncludedFiles("GENERATED_SOURCES"); } - virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &); - inline QString replaceExtraCompilerVariables(const QString &val, const QString &in, const QString &out) - { return MakefileGenerator::replaceExtraCompilerVariables(val, in, out); } - virtual bool supportsMetaBuild() { return true; } - virtual bool supportsMergedBuilds() { return true; } - virtual bool mergeBuildProject(MakefileGenerator *other); - virtual void processPrlVariable(const QString &, const QStringList &); - virtual bool findLibraries(); - - bool usePCH; - QString precompH, namePCH, - precompObj, precompPch; - - QString platform; - - struct BuildStep { - BuildStep() {} - BuildStep &operator<<(const BuildStep &other) { - deps << other.deps; - buildStep += other.buildStep; - buildName += other.buildName; - buildOutputs += other.buildOutputs; - return *this; - } - - QStringList deps; - QString buildStep; - QString buildName; - QStringList buildOutputs; - }; - QMap<QString, BuildStep> swappedBuildSteps; - - // Holds all configurations for glue (merged) project - QList<DspMakefileGenerator*> mergedProjects; -}; - -inline DspMakefileGenerator::~DspMakefileGenerator() -{ } - -inline bool DspMakefileGenerator::findLibraries() -{ return Win32MakefileGenerator::findLibraries("MSVCDSP_LIBS"); } - -QT_END_NAMESPACE - -#endif // MSVC_DSP_H diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 7566b23845..92e8aeba7f 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -156,8 +156,6 @@ void NmakeMakefileGenerator::init() MakefileGenerator::init(); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); - if(project->values("QMAKE_QMAKE").isEmpty()) - project->values("QMAKE_QMAKE").append("qmake"); if(project->isEmpty("QMAKE_COPY_FILE")) project->values("QMAKE_COPY_FILE").append("$(COPY)"); if(project->isEmpty("QMAKE_COPY_DIR")) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index ee7b228f35..980e686556 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -41,6 +41,7 @@ #include "msvc_objectmodel.h" #include "msvc_vcproj.h" +#include "msvc_vcxproj.h" #include <qstringlist.h> #include <qfileinfo.h> @@ -1429,7 +1430,8 @@ bool VCLinkerTool::parseOption(const char* option) break; case 0x0034160: // /MAP[:filename] GenerateMapFile = _True; - MapFileName = option+5; + if (option[4] == ':') + MapFileName = option+5; break; case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES} if(*(option+9) == 'E') diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index c56187ca1d..97f85702b1 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -58,7 +58,8 @@ enum DotNET { NET2002 = 0x70, NET2003 = 0x71, NET2005 = 0x80, - NET2008 = 0x90 + NET2008 = 0x90, + NET2010 = 0xa0 }; /* @@ -867,7 +868,7 @@ public: customBuildCheck CustomBuild; - bool useCustomBuildTool; + bool useCustomBuildTool; VCCustomBuildTool CustomBuildTool; bool useCompilerTool; diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 58f95e953b..8686ae829e 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -77,6 +77,8 @@ struct { const char *regKey; } dotNetCombo[] = { #ifdef Q_OS_WIN64 + {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"}, + {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"}, {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"}, {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"}, {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"}, @@ -84,6 +86,8 @@ struct { {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"}, {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"}, #else + {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"}, + {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"}, {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"}, {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"}, {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"}, @@ -165,8 +169,12 @@ DotNET which_dotnet_version() // Flatfile Tags ---------------------------------------------------- const char _slnHeader70[] = "Microsoft Visual Studio Solution File, Format Version 7.00"; const char _slnHeader71[] = "Microsoft Visual Studio Solution File, Format Version 8.00"; -const char _slnHeader80[] = "Microsoft Visual Studio Solution File, Format Version 9.00"; -const char _slnHeader90[] = "Microsoft Visual Studio Solution File, Format Version 10.00"; +const char _slnHeader80[] = "Microsoft Visual Studio Solution File, Format Version 9.00" + "\n# Visual Studio 2005"; +const char _slnHeader90[] = "Microsoft Visual Studio Solution File, Format Version 10.00" + "\n# Visual Studio 2008"; +const char _slnHeader100[] = "Microsoft Visual Studio Solution File, Format Version 11.00" + "\n# Visual Studio 2010"; // The following UUID _may_ change for later servicepacks... // If so we need to search through the registry at // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects @@ -354,6 +362,9 @@ void VcprojGenerator::writeSubDirs(QTextStream &t) } switch(which_dotnet_version()) { + case NET2010: + t << _slnHeader100; + break; case NET2008: t << _slnHeader90; break; @@ -889,6 +900,7 @@ void VcprojGenerator::initCompilerTool() conf.compiler.AssemblerListingLocation = placement ; conf.compiler.ProgramDataBaseFileName = ".\\" ; conf.compiler.ObjectFile = placement ; + conf.compiler.ExceptionHandling = ehNone; // PCH if (usePCH) { conf.compiler.UsePrecompiledHeader = pchUseUsingSpecific; @@ -906,14 +918,12 @@ void VcprojGenerator::initCompilerTool() conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); if(project->isActiveConfig("debug")){ // Debug version - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_DEBUG")); if((projectTarget == Application) || (projectTarget == StaticLib)) conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG")); else conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG")); } else { // Release version - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_RELEASE")); conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; conf.compiler.PreprocessorDefinitions += "NDEBUG"; if((projectTarget == Application) || (projectTarget == StaticLib)) @@ -923,10 +933,6 @@ void VcprojGenerator::initCompilerTool() } // Common for both release and debug - if(project->isActiveConfig("warn_off")) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_WARN_OFF")); - else if(project->isActiveConfig("warn_on")) - conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_WARN_ON")); if(project->isActiveConfig("windows")) conf.compiler.PreprocessorDefinitions += project->values("MSVCPROJ_WINCONDEF"); @@ -989,22 +995,9 @@ void VcprojGenerator::initLinkerTool() conf.linker.OutputFile += project->first("MSVCPROJ_TARGET"); - if(project->isActiveConfig("debug")){ - conf.linker.parseOptions(project->values("QMAKE_LFLAGS_DEBUG")); - } else { - conf.linker.parseOptions(project->values("QMAKE_LFLAGS_RELEASE")); - } - if(project->isActiveConfig("dll")){ conf.linker.parseOptions(project->values("QMAKE_LFLAGS_QT_DLL")); } - - if(project->isActiveConfig("console")){ - conf.linker.parseOptions(project->values("QMAKE_LFLAGS_CONSOLE")); - } else { - conf.linker.parseOptions(project->values("QMAKE_LFLAGS_WINDOWS")); - } - } void VcprojGenerator::initResourceTool() @@ -1626,8 +1619,7 @@ QString VcprojGenerator::findTemplate(QString file) !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2002/" + file))) && !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2003/" + file))) && !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2005/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file))) && - !exists((ret = (QString(qgetenv("HOME")) + "/.tmake/" + file)))) + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file)))) return ""; debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.toLatin1().constData()); return ret; diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index ed67ea7679..8f028a197e 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -61,7 +61,6 @@ class VcprojGenerator : public Win32MakefileGenerator bool writeMakefile(QTextStream &); bool writeProjectMakefile(); - void writeSubDirs(QTextStream &t); QString findTemplate(QString file); void init(); @@ -119,6 +118,9 @@ protected: void initLexYaccFiles(); void initExtraCompilerOutputs(); + void writeSubDirs(QTextStream &t); // Called from VCXProj backend + QUuid getProjectUUID(const QString &filename=QString()); // Called from VCXProj backend + Target projectTarget; // Used for single project @@ -129,7 +131,6 @@ protected: private: QString fixCommandLine(DotNET version, const QString &input) const; - QUuid getProjectUUID(const QString &filename=QString()); QUuid increaseUUID(const QUuid &id); friend class VCFilter; }; diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp new file mode 100644 index 0000000000..271d9ae29f --- /dev/null +++ b/qmake/generators/win32/msvc_vcxproj.cpp @@ -0,0 +1,836 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "msvc_vcxproj.h" +#include "msbuild_objectmodel.h" +#include <qdir.h> +#include <qdiriterator.h> +#include <quuid.h> + + +QT_BEGIN_NAMESPACE +// Filter GUIDs (Do NOT change these!) ------------------------------ +const char _GUIDSourceFiles[] = "{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"; +const char _GUIDHeaderFiles[] = "{93995380-89BD-4b04-88EB-625FBE52EBFB}"; +const char _GUIDGeneratedFiles[] = "{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}"; +const char _GUIDResourceFiles[] = "{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}"; +const char _GUIDLexYaccFiles[] = "{E12AE0D2-192F-4d59-BD23-7D3FA58D3183}"; +const char _GUIDTranslationFiles[] = "{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}"; +const char _GUIDFormFiles[] = "{99349809-55BA-4b9d-BF79-8FDBB0286EB3}"; +const char _GUIDExtraCompilerFiles[] = "{E0D8C965-CC5F-43d7-AD63-FAEF0BBC0F85}"; +QT_END_NAMESPACE + +QT_BEGIN_NAMESPACE + + +VcxprojGenerator::VcxprojGenerator() : VcprojGenerator() +{ +} +bool VcxprojGenerator::writeMakefile(QTextStream &t) +{ + initProject(); // Fills the whole project with proper data + + // Generate solution file + if(project->first("TEMPLATE") == "vcsubdirs") { + if (!project->isActiveConfig("build_pass")) { + debug_msg(1, "Generator: MSVC.NET: Writing solution file"); + writeSubDirs(t); + } else { + debug_msg(1, "Generator: MSVC.NET: Not writing solution file for build_pass configs"); + } + return true; + } else + // Generate single configuration project file + if (project->first("TEMPLATE") == "vcapp" || + project->first("TEMPLATE") == "vclib") { + if(!project->isActiveConfig("build_pass")) { + debug_msg(1, "Generator: MSVC.NET: Writing single configuration project file"); + XmlOutput xmlOut(t); + xmlOut << vcxProject; + } + return true; + } + return project->isActiveConfig("build_pass"); +} + + +void VcxprojGenerator::initProject() +{ + // Initialize XML sub elements + // - Do this first since project elements may need + // - to know of certain configuration options + initConfiguration(); + initRootFiles(); + initSourceFiles(); + initHeaderFiles(); + initGeneratedFiles(); + initLexYaccFiles(); + initTranslationFiles(); + initFormFiles(); + initResourceFiles(); + initExtraCompilerOutputs(); + + // Own elements ----------------------------- + vcxProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); + + vcxProject.Keyword = project->first("VCPROJ_KEYWORD"); + if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) { + vcxProject.PlatformName = vcxProject.Configuration.idl.TargetEnvironment; + if ( vcxProject.Configuration.idl.TargetEnvironment.isEmpty() ) + vcxProject.PlatformName = "Win32"; + } else { + vcxProject.PlatformName = project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")"; + } + // These are not used by Qt, but may be used by customers + vcxProject.SccProjectName = project->first("SCCPROJECTNAME"); + vcxProject.SccLocalPath = project->first("SCCLOCALPATH"); + vcxProject.flat_files = project->isActiveConfig("flat"); +} + + +void VcxprojGenerator::initConfiguration() +{ + // Initialize XML sub elements + // - Do this first since main configuration elements may need + // - to know of certain compiler/linker options + VCXConfiguration &conf = vcxProject.Configuration; + + initCompilerTool(); + + // Only on configuration per build + bool isDebug = project->isActiveConfig("debug"); + + if(projectTarget == StaticLib) + initLibrarianTool(); + else { + conf.linker.GenerateDebugInformation = isDebug ? _True : _False; + initLinkerTool(); + } + initResourceTool(); + initIDLTool(); + + // Own elements ----------------------------- + QString temp = project->first("BuildBrowserInformation"); + switch (projectTarget) { + case SharedLib: + conf.ConfigurationType = "DynamicLibrary"; + break; + case StaticLib: + conf.ConfigurationType = "StaticLibrary"; + break; + case Application: + default: + conf.ConfigurationType = "Application"; + break; + } + + conf.OutputDirectory = project->first("DESTDIR"); + + if(conf.OutputDirectory.isEmpty()) + conf.OutputDirectory = ".\\"; + + if(!conf.OutputDirectory.endsWith("\\")) + conf.OutputDirectory += '\\'; + + // The target name could have been changed. + conf.TargetName = project->first("TARGET"); + if ( !conf.TargetName.isEmpty() && !project->first("TARGET_VERSION_EXT").isEmpty() && project->isActiveConfig("shared")) + conf.TargetName.append(project->first("TARGET_VERSION_EXT")); + + conf.Name = project->values("BUILD_NAME").join(" "); + if (conf.Name.isEmpty()) + conf.Name = isDebug ? "Debug" : "Release"; + conf.ConfigurationName = conf.Name; + if (project->isEmpty("CE_SDK") || project->isEmpty("CE_ARCH")) { + conf.Name += (conf.idl.TargetEnvironment == "Win64" ? "|Win64" : "|Win32"); + } else { + conf.Name += "|" + project->values("CE_SDK").join(" ") + " (" + project->first("CE_ARCH") + ")"; + } + conf.ATLMinimizesCRunTimeLibraryUsage = (project->first("ATLMinimizesCRunTimeLibraryUsage").isEmpty() ? _False : _True); + conf.BuildBrowserInformation = triState(temp.isEmpty() ? (short)unset : temp.toShort()); + temp = project->first("CharacterSet"); + if (!temp.isEmpty()) + { + switch (charSet(temp.toShort())) { + + case charSetMBCS: + conf.CharacterSet = "MultiByte"; + break; + case charSetUnicode: + conf.CharacterSet = "Unicode"; + break; + case charSetNotSet: + default: + conf.CharacterSet = "NotSet"; + break; + } + } + conf.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean"); + conf.ImportLibrary = conf.linker.ImportLibrary; + conf.IntermediateDirectory = project->first("OBJECTS_DIR"); + //conf.OutputDirectory = "."; + conf.PrimaryOutput = project->first("PrimaryOutput"); + conf.WholeProgramOptimization = conf.compiler.WholeProgramOptimization; + temp = project->first("UseOfATL"); + if(!temp.isEmpty()) + { + switch (useOfATL(temp.toShort())) { + + case useATLStatic: + conf.UseOfATL = "Static"; + break; + case useATLDynamic: + conf.UseOfATL = "Dynamic"; + break; + case useATLNotSet: + default: + conf.UseOfATL = "false"; + break; + } + } + temp = project->first("UseOfMfc"); + if(!temp.isEmpty()) + { + switch (useOfMfc(temp.toShort())) { + + case useMfcStatic: + conf.UseOfMfc = "Static"; + break; + case useMfcDynamic: + conf.UseOfMfc = "Dynamic"; + break; + case useMfcStdWin: + default: + conf.UseOfMfc = "false"; + break; + } + } + + // Configuration does not need parameters from + // these sub XML items; + initCustomBuildTool(); + initPreBuildEventTools(); + initPostBuildEventTools(); + // Only deploy for CE projects + if (!project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH")) + initDeploymentTool(); + initPreLinkEventTools(); + + // Set definite values in both configurations + if (isDebug) { + conf.compiler.PreprocessorDefinitions.removeAll("NDEBUG"); + } else { + conf.compiler.PreprocessorDefinitions += "NDEBUG"; + } +} + + +void VcxprojGenerator::initCompilerTool() +{ + QString placement = project->first("OBJECTS_DIR"); + if(placement.isEmpty()) + placement = ".\\"; + + VCXConfiguration &conf = vcxProject.Configuration; + conf.compiler.AssemblerListingLocation = placement ; + conf.compiler.ProgramDataBaseFileName = ".\\" ; + conf.compiler.ObjectFileName = placement ; + conf.compiler.ExceptionHandling = "false"; + // PCH + if (usePCH) { + conf.compiler.PrecompiledHeader = "Use"; + conf.compiler.PrecompiledHeaderOutputFile = "$(IntDir)\\" + precompPch; + conf.compiler.PrecompiledHeaderFile = project->first("PRECOMPILED_HEADER"); + conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER"); + conf.compiler.PreprocessToFile = _False; + conf.compiler.PreprocessSuppressLineNumbers = _False; + // Minimal build option triggers an Internal Compiler Error + // when used in conjunction with /FI and /Yu, so remove it + project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm"); + project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm"); + project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm"); + project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm"); + } + + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS")); + if(project->isActiveConfig("debug")){ + // Debug version + if((projectTarget == Application) || (projectTarget == StaticLib)) + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DBG")); + else + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLLDBG")); + } else { + // Release version + conf.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; + conf.compiler.PreprocessorDefinitions += "NDEBUG"; + if((projectTarget == Application) || (projectTarget == StaticLib)) + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT")); + else + conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS_MT_DLL")); + } + + // Common for both release and debug + if(project->isActiveConfig("windows")) + conf.compiler.PreprocessorDefinitions += project->values("MSVCPROJ_WINCONDEF"); + + // Can this be set for ALL configs? + // If so, use qmake.conf! + if(projectTarget == SharedLib) + conf.compiler.PreprocessorDefinitions += "_WINDOWS"; + + conf.compiler.PreprocessorDefinitions += project->values("DEFINES"); + conf.compiler.PreprocessorDefinitions += project->values("PRL_EXPORT_DEFINES"); + conf.compiler.parseOptions(project->values("MSVCPROJ_INCPATH")); +} + +void VcxprojGenerator::initLinkerTool() +{ + findLibraries(); // Need to add the highest version of the libs + VCXConfiguration &conf = vcxProject.Configuration; + conf.linker.parseOptions(project->values("MSVCPROJ_LFLAGS")); + + foreach(QString libs, project->values("MSVCPROJ_LIBS")) { + if (libs.left(9).toUpper() == "/LIBPATH:") { + QStringList l = QStringList(libs); + conf.linker.parseOptions(l); + } else { + conf.linker.AdditionalDependencies += libs; + } + } + + switch (projectTarget) { + case Application: + conf.linker.OutputFile = project->first("DESTDIR"); + break; + case SharedLib: + conf.linker.parseOptions(project->values("MSVCPROJ_LIBOPTIONS")); + conf.linker.OutputFile = project->first("DESTDIR"); + break; + case StaticLib: //unhandled - added to remove warnings.. + break; + } + + if(conf.linker.OutputFile.isEmpty()) + conf.linker.OutputFile = ".\\"; + + if(!conf.linker.OutputFile.endsWith("\\")) + conf.linker.OutputFile += '\\'; + + conf.linker.OutputFile += project->first("MSVCPROJ_TARGET"); + + if(project->isActiveConfig("dll")){ + conf.linker.parseOptions(project->values("QMAKE_LFLAGS_QT_DLL")); + } +} + +void VcxprojGenerator::initResourceTool() +{ + VCXConfiguration &conf = vcxProject.Configuration; + conf.resource.PreprocessorDefinitions = conf.compiler.PreprocessorDefinitions; + + // We need to add _DEBUG for the debug version of the project, since the normal compiler defines + // do not contain it. (The compiler defines this symbol automatically, which is wy we don't need + // to add it for the compiler) However, the resource tool does not do this. + if(project->isActiveConfig("debug")) + conf.resource.PreprocessorDefinitions += "_DEBUG"; + if(project->isActiveConfig("staticlib")) + conf.resource.ResourceOutputFileName = project->first("DESTDIR") + "/$(InputName).res"; +} + + +void VcxprojGenerator::initPostBuildEventTools() +{ + VCXConfiguration &conf = vcxProject.Configuration; + if(!project->values("QMAKE_POST_LINK").isEmpty()) { + QString cmdline = var("QMAKE_POST_LINK"); + conf.postBuild.CommandLine = cmdline; + conf.postBuild.Description = cmdline; + conf.postBuild.UseInBuild = _True; + } + + QString signature = !project->isEmpty("SIGNATURE_FILE") ? var("SIGNATURE_FILE") : var("DEFAULT_SIGNATURE"); + bool useSignature = !signature.isEmpty() && !project->isActiveConfig("staticlib") && + !project->isEmpty("CE_SDK") && !project->isEmpty("CE_ARCH"); + if(useSignature) { + conf.postBuild.CommandLine.prepend(QLatin1String("signtool sign /F ") + signature + " \"$(TargetPath)\"\n" + + (!conf.postBuild.CommandLine.isEmpty() ? " && " : "")); + conf.postBuild.UseInBuild = _True; + } + + if(!project->values("MSVCPROJ_COPY_DLL").isEmpty()) { + if(!conf.postBuild.CommandLine.isEmpty()) + conf.postBuild.CommandLine += " && "; + conf.postBuild.Description += var("MSVCPROJ_COPY_DLL_DESC"); + conf.postBuild.CommandLine += var("MSVCPROJ_COPY_DLL"); + conf.postBuild.UseInBuild = _True; + } +} + + +void VcxprojGenerator::initDeploymentTool() +{ + VCXConfiguration &conf = vcxProject.Configuration; + QString targetPath = project->values("deploy.path").join(" "); + if (targetPath.isEmpty()) + targetPath = QString("%CSIDL_PROGRAM_FILES%\\") + project->first("TARGET"); + if (targetPath.endsWith("/") || targetPath.endsWith("\\")) + targetPath.chop(1); + + // Only deploy Qt libs for shared build + if (!project->values("QMAKE_QT_DLL").isEmpty()) { + QStringList& arg = project->values("MSVCPROJ_LIBS"); + for (QStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) { + if (it->contains(project->first("QMAKE_LIBDIR"))) { + QString dllName = *it; + + if (dllName.contains(QLatin1String("QAxContainer")) + || dllName.contains(QLatin1String("qtmain")) + || dllName.contains(QLatin1String("QtUiTools"))) + continue; + dllName.replace(QLatin1String(".lib") , QLatin1String(".dll")); + QFileInfo info(dllName); + conf.deployment.AdditionalFiles += info.fileName() + + "|" + QDir::toNativeSeparators(info.absolutePath()) + + "|" + targetPath + + "|0;"; + } + } + } + + // C-runtime deployment + QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" ")); + if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) { + QString runtimeVersion = QLatin1String("msvcr"); + QString mkspec = project->first("QMAKESPEC"); + // If no .qmake.cache has been found, we fallback to the original mkspec + if (mkspec.isEmpty()) + mkspec = project->first("QMAKESPEC_ORIGINAL"); + + if (!mkspec.isEmpty()) { + if (mkspec.endsWith("2010")) + runtimeVersion.append("100"); + else if (mkspec.endsWith("2008")) + runtimeVersion.append("90"); + else + runtimeVersion.append("80"); + if (project->isActiveConfig("debug")) + runtimeVersion.append("d"); + runtimeVersion.append(".dll"); + + if (runtime == "yes") { + // Auto-find C-runtime + QString vcInstallDir = qgetenv("VCINSTALLDIR"); + if (!vcInstallDir.isEmpty()) { + vcInstallDir += "\\ce\\dll\\"; + vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" ")); + if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists()) + runtime.clear(); + else + runtime = vcInstallDir; + } + } + } + + if (!runtime.isEmpty() && runtime != QLatin1String("yes")) { + conf.deployment.AdditionalFiles += runtimeVersion + + "|" + QDir::toNativeSeparators(runtime) + + "|" + targetPath + + "|0;"; + } + } + + // foreach item in DEPLOYMENT + foreach(QString item, project->values("DEPLOYMENT")) { + // get item.path + QString devicePath = project->first(item + ".path"); + if (devicePath.isEmpty()) + devicePath = targetPath; + // check if item.path is relative (! either /,\ or %) + if (!(devicePath.at(0) == QLatin1Char('/') + || devicePath.at(0) == QLatin1Char('\\') + || devicePath.at(0) == QLatin1Char('%'))) { + // create output path + devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('\\') + devicePath)); + } + // foreach d in item.sources + foreach(QString source, project->values(item + ".sources")) { + QString itemDevicePath = devicePath; + source = Option::fixPathToLocalOS(source); + QString nameFilter; + QFileInfo info(source); + QString searchPath; + if (info.isDir()) { + nameFilter = QLatin1String("*"); + itemDevicePath += "\\" + info.fileName(); + searchPath = info.absoluteFilePath(); + } else { + nameFilter = source.split('\\').last(); + searchPath = info.absolutePath(); + } + + int pathSize = searchPath.size(); + QDirIterator iterator(searchPath, QStringList() << nameFilter + , QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks + , QDirIterator::Subdirectories); + // foreach dirIterator-entry in d + while(iterator.hasNext()) { + iterator.next(); + QString absoluteItemPath = Option::fixPathToLocalOS(QFileInfo(iterator.filePath()).absolutePath()); + // Identify if it is just another subdir + int diffSize = absoluteItemPath.size() - pathSize; + // write out rules + conf.deployment.AdditionalFiles += iterator.fileName() + + "|" + absoluteItemPath + + "|" + itemDevicePath + (diffSize ? (absoluteItemPath.right(diffSize)) : QLatin1String("")) + + "|0;"; + } + } + } +} + +void VcxprojGenerator::initPreLinkEventTools() +{ + VCXConfiguration &conf = vcxProject.Configuration; + if(!project->values("QMAKE_PRE_LINK").isEmpty()) { + QString cmdline = var("QMAKE_PRE_LINK"); + conf.preLink.Description = cmdline; + conf.preLink.CommandLine = cmdline; + conf.preLink.UseInBuild = _True; + } +} + +void VcxprojGenerator::initRootFiles() +{ + vcxProject.RootFiles.addFiles(project->values("RC_FILE")); + vcxProject.RootFiles.Project = this; + vcxProject.RootFiles.Config = &(vcxProject.Configuration); + vcxProject.RootFiles.CustomBuild = none; +} + +void VcxprojGenerator::initSourceFiles() +{ + vcxProject.SourceFiles.Name = "Source Files"; + vcxProject.SourceFiles.Filter = "cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"; + vcxProject.SourceFiles.Guid = _GUIDSourceFiles; + + vcxProject.SourceFiles.addFiles(project->values("SOURCES")); + + vcxProject.SourceFiles.Project = this; + vcxProject.SourceFiles.Config = &(vcxProject.Configuration); + vcxProject.SourceFiles.CustomBuild = none; +} + +void VcxprojGenerator::initHeaderFiles() +{ + vcxProject.HeaderFiles.Name = "Header Files"; + vcxProject.HeaderFiles.Filter = "h;hpp;hxx;hm;inl;inc;xsd"; + vcxProject.HeaderFiles.Guid = _GUIDHeaderFiles; + + vcxProject.HeaderFiles.addFiles(project->values("HEADERS")); + if (usePCH) // Generated PCH cpp file + vcxProject.HeaderFiles.addFile(precompH); + + vcxProject.HeaderFiles.Project = this; + vcxProject.HeaderFiles.Config = &(vcxProject.Configuration); +} + +void VcxprojGenerator::initGeneratedFiles() +{ + vcxProject.GeneratedFiles.Name = "Generated Files"; + vcxProject.GeneratedFiles.Filter = "cpp;c;cxx;moc;h;def;odl;idl;res"; + vcxProject.GeneratedFiles.Guid = _GUIDGeneratedFiles; + + // ### These cannot have CustomBuild (mocSrc)!! + vcxProject.GeneratedFiles.addFiles(project->values("GENERATED_SOURCES")); + vcxProject.GeneratedFiles.addFiles(project->values("GENERATED_FILES")); + vcxProject.GeneratedFiles.addFiles(project->values("IDLSOURCES")); + vcxProject.GeneratedFiles.addFiles(project->values("RES_FILE")); + vcxProject.GeneratedFiles.addFiles(project->values("QMAKE_IMAGE_COLLECTION")); // compat + if(!extraCompilerOutputs.isEmpty()) + vcxProject.GeneratedFiles.addFiles(extraCompilerOutputs.keys()); + + vcxProject.GeneratedFiles.Project = this; + vcxProject.GeneratedFiles.Config = &(vcxProject.Configuration); +} + +void VcxprojGenerator::initLexYaccFiles() +{ + vcxProject.LexYaccFiles.Name = "Lex / Yacc Files"; + vcxProject.LexYaccFiles.ParseFiles = _False; + vcxProject.LexYaccFiles.Filter = "l;y"; + vcxProject.LexYaccFiles.Guid = _GUIDLexYaccFiles; + + vcxProject.LexYaccFiles.addFiles(project->values("LEXSOURCES")); + vcxProject.LexYaccFiles.addFiles(project->values("YACCSOURCES")); + + vcxProject.LexYaccFiles.Project = this; + vcxProject.LexYaccFiles.Config = &(vcxProject.Configuration); + vcxProject.LexYaccFiles.CustomBuild = lexyacc; +} + +void VcxprojGenerator::initTranslationFiles() +{ + vcxProject.TranslationFiles.Name = "Translation Files"; + vcxProject.TranslationFiles.ParseFiles = _False; + vcxProject.TranslationFiles.Filter = "ts;xlf"; + vcxProject.TranslationFiles.Guid = _GUIDTranslationFiles; + + vcxProject.TranslationFiles.addFiles(project->values("TRANSLATIONS")); + + vcxProject.TranslationFiles.Project = this; + vcxProject.TranslationFiles.Config = &(vcxProject.Configuration); + vcxProject.TranslationFiles.CustomBuild = none; +} + + +void VcxprojGenerator::initFormFiles() +{ + vcxProject.FormFiles.Name = "Form Files"; + vcxProject.FormFiles.ParseFiles = _False; + vcxProject.FormFiles.Filter = "ui"; + vcxProject.FormFiles.Guid = _GUIDFormFiles; + + vcxProject.FormFiles.addFiles(project->values("FORMS")); + vcxProject.FormFiles.addFiles(project->values("FORMS3")); + + vcxProject.FormFiles.Project = this; + vcxProject.FormFiles.Config = &(vcxProject.Configuration); + vcxProject.FormFiles.CustomBuild = none; +} + + +void VcxprojGenerator::initResourceFiles() +{ + vcxProject.ResourceFiles.Name = "Resource Files"; + vcxProject.ResourceFiles.ParseFiles = _False; + vcxProject.ResourceFiles.Filter = "qrc;*"; //"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;ts;xlf;qrc"; + vcxProject.ResourceFiles.Guid = _GUIDResourceFiles; + + // Bad hack, please look away ------------------------------------- + QString rcc_dep_cmd = project->values("rcc.depend_command").join(" "); + if(!rcc_dep_cmd.isEmpty()) { + QStringList qrc_files = project->values("RESOURCES"); + QStringList deps; + if(!qrc_files.isEmpty()) { + for (int i = 0; i < qrc_files.count(); ++i) { + char buff[256]; + QString dep_cmd = replaceExtraCompilerVariables(rcc_dep_cmd, qrc_files.at(i),""); + + dep_cmd = Option::fixPathToLocalOS(dep_cmd, true, false); + if(canExecute(dep_cmd)) { + if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + QString indeps; + while(!feof(proc)) { + int read_in = (int)fread(buff, 1, 255, proc); + if(!read_in) + break; + indeps += QByteArray(buff, read_in); + } + QT_PCLOSE(proc); + if(!indeps.isEmpty()) + deps += fileFixify(indeps.replace('\n', ' ').simplified().split(' ')); + } + } + } + vcxProject.ResourceFiles.addFiles(deps); + } + } + // You may look again -------------------------------------------- + + vcxProject.ResourceFiles.addFiles(project->values("RESOURCES")); + vcxProject.ResourceFiles.addFiles(project->values("IMAGES")); + + vcxProject.ResourceFiles.Project = this; + vcxProject.ResourceFiles.Config = &(vcxProject.Configuration); + vcxProject.ResourceFiles.CustomBuild = none; +} + +void VcxprojGenerator::initExtraCompilerOutputs() +{ + QStringList otherFilters; + otherFilters << "FORMS" + << "FORMS3" + << "GENERATED_FILES" + << "GENERATED_SOURCES" + << "HEADERS" + << "IDLSOURCES" + << "IMAGES" + << "LEXSOURCES" + << "QMAKE_IMAGE_COLLECTION" + << "RC_FILE" + << "RESOURCES" + << "RES_FILE" + << "SOURCES" + << "TRANSLATIONS" + << "YACCSOURCES"; + const QStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); + for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { + QString extracompilerName = project->first((*it) + ".name"); + if (extracompilerName.isEmpty()) + extracompilerName = (*it); + + // Create an extra compiler filter and add the files + VCXFilter extraCompile; + extraCompile.Name = extracompilerName; + extraCompile.ParseFiles = _False; + extraCompile.Filter = ""; + extraCompile.Guid = QString(_GUIDExtraCompilerFiles) + "-" + (*it); + + // If the extra compiler has a variable_out set the output file + // is added to an other file list, and does not need its own.. + bool addOnInput = hasBuiltinCompiler(project->first((*it) + ".output")); + QString tmp_other_out = project->first((*it) + ".variable_out"); + if (!tmp_other_out.isEmpty() && !addOnInput) + continue; + + if (!addOnInput) { + QString tmp_out = project->first((*it) + ".output"); + if (project->values((*it) + ".CONFIG").indexOf("combine") != -1) { + // Combined output, only one file result + extraCompile.addFile( + Option::fixPathToTargetOS(replaceExtraCompilerVariables(tmp_out, QString(), QString()), false)); + } else { + // One output file per input + QStringList tmp_in = project->values(project->first((*it) + ".input")); + for (int i = 0; i < tmp_in.count(); ++i) { + const QString &filename = tmp_in.at(i); + if (extraCompilerSources.contains(filename)) + extraCompile.addFile( + Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, tmp_out, QString()), false)); + } + } + } else { + // In this case we the outputs have a built-in compiler, so we cannot add the custom + // build steps there. So, we turn it around and add it to the input files instead, + // provided that the input file variable is not handled already (those in otherFilters + // are handled, so we avoid them). + QStringList inputVars = project->values((*it) + ".input"); + foreach(QString inputVar, inputVars) { + if (!otherFilters.contains(inputVar)) { + QStringList tmp_in = project->values(inputVar); + for (int i = 0; i < tmp_in.count(); ++i) { + const QString &filename = tmp_in.at(i); + if (extraCompilerSources.contains(filename)) + extraCompile.addFile( + Option::fixPathToTargetOS(replaceExtraCompilerVariables(filename, QString(), QString()), false)); + } + } + } + } + extraCompile.Project = this; + extraCompile.Config = &(vcxProject.Configuration); + extraCompile.CustomBuild = none; + + vcxProject.ExtraCompilersFiles.append(extraCompile); + } +} + + + +bool VcxprojGenerator::writeProjectMakefile() +{ + usePlatformDir(); + QTextStream t(&Option::output); + + // Check if all requirements are fulfilled + if(!project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) { + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").toLatin1().constData()); + return true; + } + + // Generate project file + if(project->first("TEMPLATE") == "vcapp" || + project->first("TEMPLATE") == "vclib") { + if (!mergedProjects.count()) { + warn_msg(WarnLogic, "Generator: MSVC.NET: no single configuration created, cannot output project!"); + return false; + } + + debug_msg(1, "Generator: MSVC.NET: Writing project file"); + VCXProject mergedProject; + for (int i = 0; i < mergedProjects.count(); ++i) { + VCXProjectSingleConfig *singleProject = &(mergedProjects.at(i)->vcxProject); + mergedProject.SingleProjects += *singleProject; + for (int j = 0; j < singleProject->ExtraCompilersFiles.count(); ++j) { + const QString &compilerName = singleProject->ExtraCompilersFiles.at(j).Name; + if (!mergedProject.ExtraCompilers.contains(compilerName)) + mergedProject.ExtraCompilers += compilerName; + } + } + + if(mergedProjects.count() > 1 && + mergedProjects.at(0)->vcxProject.Name == + mergedProjects.at(1)->vcxProject.Name) + mergedProjects.at(0)->writePrlFile(); + mergedProject.Name = unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); + mergedProject.Version = mergedProjects.at(0)->vcxProject.Version; + mergedProject.ProjectGUID = project->isEmpty("QMAKE_UUID") ? getProjectUUID().toString().toUpper() : project->first("QMAKE_UUID"); + mergedProject.Keyword = project->first("VCPROJ_KEYWORD"); + mergedProject.SccProjectName = mergedProjects.at(0)->vcxProject.SccProjectName; + mergedProject.SccLocalPath = mergedProjects.at(0)->vcxProject.SccLocalPath; + mergedProject.PlatformName = mergedProjects.at(0)->vcxProject.PlatformName; + + XmlOutput xmlOut(t); + xmlOut << mergedProject; + return true; + } else if(project->first("TEMPLATE") == "vcsubdirs") { + return writeMakefile(t); + } + return false; +} + + + + +bool VcxprojGenerator::mergeBuildProject(MakefileGenerator *other) +{ + VcxprojGenerator *otherVC = static_cast<VcxprojGenerator*>(other); + if (!otherVC) { + warn_msg(WarnLogic, "VcxprojGenerator: Cannot merge other types of projects! (ignored)"); + return false; + } + mergedProjects += otherVC; + return true; +} + +QT_END_NAMESPACE + diff --git a/qmake/generators/win32/msvc_vcxproj.h b/qmake/generators/win32/msvc_vcxproj.h new file mode 100644 index 0000000000..8a183e9a37 --- /dev/null +++ b/qmake/generators/win32/msvc_vcxproj.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MSVC_VCXPROJ_H +#define MSVC_VCXPROJ_H + +#include "winmakefile.h" +#include "msbuild_objectmodel.h" +#include "msvc_vcproj.h" + +QT_BEGIN_NAMESPACE + +class VcxprojGenerator : public VcprojGenerator +{ + bool writeMakefile(QTextStream &); + bool writeProjectMakefile(); + +public: + VcxprojGenerator(); + ~VcxprojGenerator(); + +protected: + virtual bool supportsMetaBuild() { return true; } + virtual bool supportsMergedBuilds() { return true; } + virtual bool mergeBuildProject(MakefileGenerator *other); + + virtual void initProject(); + + void initConfiguration(); + void initCompilerTool(); + void initDeploymentTool(); + void initLinkerTool(); + void initPreLinkEventTools(); + void initPostBuildEventTools(); + void initRootFiles(); + void initResourceTool(); + void initSourceFiles(); + void initHeaderFiles(); + void initGeneratedFiles(); + void initTranslationFiles(); + void initFormFiles(); + void initResourceFiles(); + void initLexYaccFiles(); + void initExtraCompilerOutputs(); + + // Used for single project + VCXProjectSingleConfig vcxProject; + + // Holds all configurations for glue (merged) project + QList<VcxprojGenerator*> mergedProjects; + +private: + friend class VCXFilter; + +}; + +inline VcxprojGenerator::~VcxprojGenerator() +{ } + +QT_END_NAMESPACE + +#endif // MSVC_VCXPROJ_H diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 4944d06a03..ecb20c70f9 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -598,8 +598,7 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) writeIncPart(t); writeLibsPart(t); - t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : - Option::fixPathToTargetOS(var("QMAKE_QMAKE"), false)) << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : Option::fixPathToTargetOS(var("QMAKE_IDC"), false)) << endl; t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : @@ -771,6 +770,11 @@ QString Win32MakefileGenerator::getLibTarget() return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".lib"); } +QString Win32MakefileGenerator::getPdbTarget() +{ + return QString(project->first("TARGET") + project->first("TARGET_VERSION_EXT") + ".pdb"); +} + QString Win32MakefileGenerator::defaultInstall(const QString &t) { if((t != "target" && t != "dlltarget") || @@ -811,6 +815,18 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) uninst.append("\n\t"); uninst.append("-$(DEL_FILE) \"" + dst_targ + "\""); } + if(project->isActiveConfig("shared") && project->isActiveConfig("debug")) { + QString pdb_target = getPdbTarget(); + pdb_target.remove('"'); + QString src_targ = (project->isEmpty("DESTDIR") ? QString("$(DESTDIR)") : project->first("DESTDIR")) + pdb_target; + QString dst_targ = filePrefixRoot(root, fileFixify(targetdir + pdb_target, FileFixifyAbsolute)); + if(!ret.isEmpty()) + ret += "\n\t"; + ret += QString("-$(INSTALL_FILE)") + " \"" + src_targ + "\" \"" + dst_targ + "\""; + if(!uninst.isEmpty()) + uninst.append("\n\t"); + uninst.append("-$(DEL_FILE) \"" + dst_targ + "\""); + } } if(t == "dlltarget" || project->values(t + ".CONFIG").indexOf("no_dll") == -1) { diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h index 5437524495..3a2e3a1ee8 100644 --- a/qmake/generators/win32/winmakefile.h +++ b/qmake/generators/win32/winmakefile.h @@ -83,6 +83,7 @@ protected: virtual void processRcFileVar(); virtual void processFileTagsVar(); virtual QString getLibTarget(); + virtual QString getPdbTarget(); }; inline Win32MakefileGenerator::~Win32MakefileGenerator() diff --git a/qmake/generators/xmloutput.cpp b/qmake/generators/xmloutput.cpp index e8578aa6e4..718bdd6d45 100644 --- a/qmake/generators/xmloutput.cpp +++ b/qmake/generators/xmloutput.cpp @@ -81,6 +81,11 @@ void XmlOutput::setState(XMLState state) currentState = state; } +void XmlOutput::setFormat(XMLFormat newFormat) +{ + format = newFormat; +} + XmlOutput::XMLState XmlOutput::state() { return currentState; @@ -172,6 +177,20 @@ XmlOutput& XmlOutput::operator<<(const xml_output& o) case tTag: newTagOpen(o.xo_text); break; + case tTagValue: + addRaw(QString("\n%1<%2>").arg(currentIndent).arg(o.xo_text)); + addRaw(QString("%1").arg(o.xo_value)); + addRaw(QString("</%1>").arg(o.xo_text)); + break; + case tValueTag: + addRaw(QString("%1").arg(doConversion(o.xo_text))); + setFormat(NoNewLine); + closeTag(); + setFormat(NewLine); + break; + case tImport: + addRaw(QString("\n%1<Import %2=\"%3\" />").arg(currentIndent).arg(o.xo_text).arg(o.xo_value)); + break; case tCloseTag: if (o.xo_value.count()) closeAll(); @@ -183,6 +202,9 @@ XmlOutput& XmlOutput::operator<<(const xml_output& o) case tAttribute: addAttribute(o.xo_text, o.xo_value); break; + case tAttributeTag: + addAttributeTag(o.xo_text, o.xo_value); + break; case tData: { // Special case to be able to close tag in normal @@ -266,7 +288,7 @@ void XmlOutput::closeTag() tagStack.pop_back(); break; case Attribute: - xmlFile << "/>"; + xmlFile << " />"; tagStack.pop_back(); currentState = Tag; decreaseIndent(); // <--- Post-decrease indent @@ -307,7 +329,7 @@ void XmlOutput::addDeclaration(const QString &version, const QString &encoding) qDebug("<%s>: Cannot add declaration when not in bare state", tagStack.last().toLatin1().constData()); return; } - QString outData = QString("<?xml version=\"%1\" encoding = \"%2\"?>") + QString outData = QString("<?xml version=\"%1\" encoding=\"%2\"?>") .arg(doConversion(version)) .arg(doConversion(encoding)); addRaw(outData); @@ -337,4 +359,20 @@ void XmlOutput::addAttribute(const QString &attribute, const QString &value) xmlFile << currentIndent << doConversion(attribute) << "=\"" << doConversion(value) << "\""; } +void XmlOutput::addAttributeTag(const QString &attribute, const QString &value) +{ + switch(currentState) { + case Bare: + case Tag: + //warn_msg(WarnLogic, "<%s>: Cannot add attribute since tags not open", tagStack.last().toLatin1().constData()); + qDebug("<%s>: Cannot add attribute (%s) since tag's not open", + (tagStack.count() ? tagStack.last().toLatin1().constData() : "Root"), + attribute.toLatin1().constData()); + return; + case Attribute: + break; + } + xmlFile << " " << doConversion(attribute) << "=\"" << doConversion(value) << "\""; +} + QT_END_NAMESPACE diff --git a/qmake/generators/xmloutput.h b/qmake/generators/xmloutput.h index a472c99349..7c0667c0e4 100644 --- a/qmake/generators/xmloutput.h +++ b/qmake/generators/xmloutput.h @@ -69,9 +69,13 @@ public: tRaw, // Raw text (no formating) tDeclaration, // <?xml version="x.x" encoding="xxx"?> tTag, // <tagname attribute1="value" + tTagValue, // <tagname>value</tagname> + tValueTag, // value</tagname> tCloseTag, // Closes an open tag tAttribute, // attribute2="value"> + tAttributeTag, // attribute on the same line as a tag tData, // Tag data (formating done) + tImport, // <import "type"="path" /> tComment, // <!-- Comment --> tCDATA // <![CDATA[ ... ]]> }; @@ -85,6 +89,7 @@ public: void setIndentLevel(int level); int indentLevel(); void setState(XMLState state); + void setFormat(XMLFormat newFormat); XMLState state(); @@ -121,6 +126,7 @@ private: void addDeclaration(const QString &version, const QString &encoding); void addRaw(const QString &rawText); void addAttribute(const QString &attribute, const QString &value); + void addAttributeTag(const QString &attribute, const QString &value); void addData(const QString &data); // Data @@ -163,6 +169,22 @@ inline XmlOutput::xml_output tag(const QString &name) return XmlOutput::xml_output(XmlOutput::tTag, name, QString()); } + +inline XmlOutput::xml_output valueTag(const QString &value) +{ + return XmlOutput::xml_output(XmlOutput::tValueTag, value, QString()); +} + +inline XmlOutput::xml_output tagValue(const QString &tagName, const QString &value) +{ + return XmlOutput::xml_output(XmlOutput::tTagValue, tagName, value); +} + +inline XmlOutput::xml_output import(const QString &tagName, const QString &value) +{ + return XmlOutput::xml_output(XmlOutput::tImport, tagName, value); +} + inline XmlOutput::xml_output closetag() { return XmlOutput::xml_output(XmlOutput::tCloseTag, QString(), QString()); @@ -184,12 +206,24 @@ inline XmlOutput::xml_output attribute(const QString &name, return XmlOutput::xml_output(XmlOutput::tAttribute, name, value); } +inline XmlOutput::xml_output attributeTag(const QString &name, + const QString &value) +{ + return XmlOutput::xml_output(XmlOutput::tAttributeTag, name, value); +} + inline XmlOutput::xml_output attr(const QString &name, const QString &value) { return attribute(name, value); } +inline XmlOutput::xml_output attrTag(const QString &name, + const QString &value) +{ + return attributeTag(name, value); +} + inline XmlOutput::xml_output data(const QString &text = QString()) { return XmlOutput::xml_output(XmlOutput::tData, text, QString()); diff --git a/qmake/main.cpp b/qmake/main.cpp index 50f9272e22..42679a2e93 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -149,7 +149,7 @@ int runQMake(int argc, char **argv) //setup pwd properly debug_msg(1, "Resetting dir to: %s", oldpwd.toLatin1().constData()); qmake_setpwd(oldpwd); //reset the old pwd - int di = fn.lastIndexOf(Option::dir_sep); + int di = fn.lastIndexOf(QDir::separator()); if(di != -1) { debug_msg(1, "Changing dir to: %s", fn.left(di).toLatin1().constData()); if(!qmake_setpwd(fn.left(di))) diff --git a/qmake/option.cpp b/qmake/option.cpp index 5522a808a9..8db3797612 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -84,11 +84,11 @@ Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING; //all modes QString Option::qmake_abslocation; -int Option::warn_level = WarnLogic; +int Option::warn_level = WarnLogic | WarnDeprecated; int Option::debug_level = 0; QFile Option::output; QString Option::output_dir; -bool Option::recursive = false; +Option::QMAKE_RECURSIVE Option::recursive = Option::QMAKE_RECURSIVE_DEFAULT; QStringList Option::before_user_vars; QStringList Option::after_user_vars; QStringList Option::user_configs; @@ -96,13 +96,9 @@ QStringList Option::after_user_configs; QString Option::user_template; QString Option::user_template_prefix; QStringList Option::shellPath; -#if defined(Q_OS_WIN32) -Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE; -#elif defined(Q_OS_MAC) -Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE; -#else -Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE; -#endif +Option::HOST_MODE Option::host_mode = Option::HOST_UNKNOWN_MODE; +Option::TARG_MODE Option::target_mode = Option::TARG_UNKNOWN_MODE; +bool Option::target_mode_overridden = false; //QMAKE_*_PROPERTY stuff QStringList Option::prop::properties; @@ -126,7 +122,7 @@ QString Option::mkfile::qmakespec_commandline; static Option::QMAKE_MODE default_mode(QString progname) { - int s = progname.lastIndexOf(Option::dir_sep); + int s = progname.lastIndexOf(QDir::separator()); if(s != -1) progname = progname.right(progname.length() - (s + 1)); if(progname == "qmakegen") @@ -136,6 +132,20 @@ static Option::QMAKE_MODE default_mode(QString progname) return Option::QMAKE_GENERATE_MAKEFILE; } +static QString detectProjectFile(const QString &path) +{ + QString ret; + QDir dir(path); + if(dir.exists(dir.dirName() + Option::pro_ext)) { + ret = dir.filePath(dir.dirName()) + Option::pro_ext; + } else { //last try.. + QStringList profiles = dir.entryList(QStringList("*" + Option::pro_ext)); + if(profiles.count() == 1) + ret = dir.filePath(profiles.at(0)); + } + return ret; +} + QString project_builtin_regx(); bool usage(const char *a0) { @@ -160,19 +170,18 @@ bool usage(const char *a0) " file in your current working directory\n" "\n" "Warnings Options:\n" - " -Wnone Turn off all warnings\n" + " -Wnone Turn off all warnings; specific ones may be re-enabled by\n" + " later -W options\n" " -Wall Turn on all warnings\n" " -Wparser Turn on parser warnings\n" - " -Wlogic Turn on logic warnings\n" + " -Wlogic Turn on logic warnings (on by default)\n" + " -Wdeprecated Turn on deprecation warnings (on by default)\n" "\n" "Options:\n" " * You can place any variable assignment in options and it will be *\n" " * processed as if it was in [files]. These assignments will be parsed *\n" " * before [files]. *\n" " -o file Write output to file\n" - " -unix Run in unix mode\n" - " -win32 Run in win32 mode\n" - " -macx Run in Mac OS X mode\n" " -d Increase debug level\n" " -t templ Overrides TEMPLATE as templ\n" " -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n" @@ -209,7 +218,7 @@ Option::parseCommandLine(int argc, char **argv, int skip) if(x == 1) { bool specified = true; if(opt == "project") { - Option::recursive = true; + Option::recursive = Option::QMAKE_RECURSIVE_YES; Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT; } else if(opt == "prl") { Option::mkfile::do_deps = false; @@ -236,14 +245,21 @@ Option::parseCommandLine(int argc, char **argv, int skip) Option::user_template = argv[++x]; } else if(opt == "tp" || opt == "template_prefix") { Option::user_template_prefix = argv[++x]; - } else if(opt == "mac9") { - Option::target_mode = TARG_MAC9_MODE; } else if(opt == "macx") { + fprintf(stderr, "-macx is deprecated.\n"); + Option::host_mode = HOST_MACX_MODE; Option::target_mode = TARG_MACX_MODE; + Option::target_mode_overridden = true; } else if(opt == "unix") { + fprintf(stderr, "-unix is deprecated.\n"); + Option::host_mode = HOST_UNIX_MODE; Option::target_mode = TARG_UNIX_MODE; + Option::target_mode_overridden = true; } else if(opt == "win32") { + fprintf(stderr, "-win32 is deprecated.\n"); + Option::host_mode = HOST_WIN_MODE; Option::target_mode = TARG_WIN_MODE; + Option::target_mode_overridden = true; } else if(opt == "d") { Option::debug_level++; } else if(opt == "version" || opt == "v" || opt == "-version") { @@ -264,12 +280,14 @@ Option::parseCommandLine(int argc, char **argv, int skip) Option::warn_level |= WarnParser; } else if(opt == "Wlogic") { Option::warn_level |= WarnLogic; + } else if(opt == "Wdeprecated") { + Option::warn_level |= WarnDeprecated; } else if(opt == "Wnone") { Option::warn_level = WarnNone; } else if(opt == "r" || opt == "recursive") { - Option::recursive = true; - } else if(opt == "norecursive") { - Option::recursive = false; + Option::recursive = Option::QMAKE_RECURSIVE_YES; + } else if(opt == "nr" || opt == "norecursive") { + Option::recursive = Option::QMAKE_RECURSIVE_NO; } else if(opt == "config") { Option::user_configs += argv[++x]; } else { @@ -286,6 +304,7 @@ Option::parseCommandLine(int argc, char **argv, int skip) } else if(opt == "nodependheuristics") { Option::mkfile::do_dep_heuristics = false; } else if(opt == "E") { + fprintf(stderr, "-E is deprecated. Use -d instead.\n"); Option::mkfile::do_preprocess = true; } else if(opt == "cache") { Option::mkfile::cachefile = argv[++x]; @@ -322,12 +341,18 @@ Option::parseCommandLine(int argc, char **argv, int skip) if(!fi.makeAbsolute()) //strange arg = fi.filePath(); if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || - Option::qmake_mode == Option::QMAKE_GENERATE_PRL) + Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { + if(fi.isDir()) { + QString proj = detectProjectFile(arg); + if (!proj.isNull()) + arg = proj; + } Option::mkfile::project_files.append(arg); - else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) + } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { Option::projfile::project_dirs.append(arg); - else + } else { handled = false; + } } if(!handled) { return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; @@ -387,8 +412,10 @@ Option::init(int argc, char **argv) #ifdef Q_OS_WIN Option::dirlist_sep = ";"; Option::shellPath = detectShellPath(); + Option::res_ext = ".res"; #else Option::dirlist_sep = ":"; + Option::shellPath = QStringList("sh"); #endif Option::sysenv_mod = "QMAKE_ENV_"; Option::field_sep = ' '; @@ -494,15 +521,9 @@ Option::init(int argc, char **argv) //try REALLY hard to do it for them, lazy.. if(Option::mkfile::project_files.isEmpty()) { - QString pwd = qmake_getpwd(), - proj = pwd + "/" + pwd.right(pwd.length() - (pwd.lastIndexOf('/') + 1)) + Option::pro_ext; - if(QFile::exists(proj)) { + QString proj = detectProjectFile(qmake_getpwd()); + if(!proj.isNull()) Option::mkfile::project_files.append(proj); - } else { //last try.. - QStringList profiles = QDir(pwd).entryList(QStringList("*" + Option::pro_ext)); - if(profiles.count() == 1) - Option::mkfile::project_files.append(pwd + "/" + profiles[0]); - } #ifndef QT_BUILD_QMAKE_LIBRARY if(Option::mkfile::project_files.isEmpty()) { usage(argv[0]); @@ -510,24 +531,36 @@ Option::init(int argc, char **argv) } #endif } + } else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { +#if defined(Q_OS_MAC) + Option::host_mode = Option::HOST_MACX_MODE; + Option::target_mode = Option::TARG_MACX_MODE; +#elif defined(Q_OS_UNIX) + Option::host_mode = Option::HOST_UNIX_MODE; + Option::target_mode = Option::TARG_UNIX_MODE; +#else + Option::host_mode = Option::HOST_WIN_MODE; + Option::target_mode = Option::TARG_WIN_MODE; +#endif } //defaults for globals - if(Option::target_mode == Option::TARG_WIN_MODE) { - Option::dir_sep = "\\"; - Option::obj_ext = ".obj"; - Option::res_ext = ".res"; - } else { - if(Option::target_mode == Option::TARG_MAC9_MODE) - Option::dir_sep = ":"; - else - Option::dir_sep = "/"; - Option::obj_ext = ".o"; - } - Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation); + if (Option::host_mode != Option::HOST_UNKNOWN_MODE) + applyHostMode(); return QMAKE_CMDLINE_SUCCESS; } +void Option::applyHostMode() +{ + if (Option::host_mode == Option::HOST_WIN_MODE) { + Option::dir_sep = "\\"; + Option::obj_ext = ".obj"; + } else { + Option::dir_sep = "/"; + Option::obj_ext = ".o"; + } +} + bool Option::postProcessProject(QMakeProject *project) { Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"]; @@ -584,7 +617,7 @@ bool Option::postProcessProject(QMakeProject *project) QString Option::fixString(QString string, uchar flags) { - const QString orig_string = string; + //const QString orig_string = string; static QHash<FixStringCacheKey, QString> *cache = 0; if(!cache) { cache = new QHash<FixStringCacheKey, QString>; diff --git a/qmake/option.h b/qmake/option.h index fe9a4ef798..b09ead2765 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -63,6 +63,7 @@ enum QMakeWarn { WarnNone = 0x00, WarnParser = 0x01, WarnLogic = 0x02, + WarnDeprecated = 0x04, WarnAll = 0xFF }; void warn_msg(QMakeWarn t, const char *fmt, ...); @@ -106,6 +107,7 @@ struct Option //both of these must be called.. static int init(int argc=0, char **argv=0); //parse cmdline + static void applyHostMode(); static bool postProcessProject(QMakeProject *); enum StringFixFlags { @@ -148,10 +150,15 @@ struct Option static QString output_dir; static int debug_level; static int warn_level; - static bool recursive; + enum QMAKE_RECURSIVE { QMAKE_RECURSIVE_DEFAULT, QMAKE_RECURSIVE_YES, QMAKE_RECURSIVE_NO }; + static QMAKE_RECURSIVE recursive; static QStringList before_user_vars, after_user_vars, user_configs, after_user_configs; - enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE }; + enum HOST_MODE { HOST_UNKNOWN_MODE, HOST_UNIX_MODE, HOST_WIN_MODE, HOST_MACX_MODE }; + static HOST_MODE host_mode; + enum TARG_MODE { TARG_UNKNOWN_MODE, TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, + TARG_SYMBIAN_MODE }; static TARG_MODE target_mode; + static bool target_mode_overridden; static QString user_template, user_template_prefix; static QStringList shellPath; @@ -205,7 +212,8 @@ public: TranslationsPath, SettingsPath, DemosPath, - ExamplesPath + ExamplesPath, + ImportsPath }; static QString location(LibraryLocation); }; diff --git a/qmake/project.cpp b/qmake/project.cpp index e4ef7ddcc5..cb029234e2 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -43,6 +43,7 @@ #include "property.h" #include "option.h" #include "cachekeys.h" +#include "generators/metamakefile.h" #include <qdatetime.h> #include <qfile.h> @@ -121,7 +122,7 @@ enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR, - T_MESSAGE, T_WARNING, T_IF }; + T_MESSAGE, T_WARNING, T_IF, T_OPTION }; QMap<QString, TestFunc> qmake_testFunctions() { static QMap<QString, TestFunc> *qmake_test_functions = 0; @@ -155,6 +156,7 @@ QMap<QString, TestFunc> qmake_testFunctions() qmake_test_functions->insert("error", T_ERROR); qmake_test_functions->insert("message", T_MESSAGE); qmake_test_functions->insert("warning", T_WARNING); + qmake_test_functions->insert("option", T_OPTION); } return *qmake_test_functions; } @@ -184,9 +186,7 @@ static QString remove_quotes(const QString &arg) static QString varMap(const QString &x) { QString ret(x); - if(ret.startsWith("TMAKE")) //tmake no more! - ret = "QMAKE" + ret.mid(5); - else if(ret == "INTERFACES") + if(ret == "INTERFACES") ret = "FORMS"; else if(ret == "QMAKE_POST_BUILD") ret = "QMAKE_POST_LINK"; @@ -220,6 +220,11 @@ static QString varMap(const QString &x) ret = "QMAKE_FRAMEWORKPATH"; else if(ret == "QMAKE_FRAMEWORKDIR_FLAGS") ret = "QMAKE_FRAMEWORKPATH_FLAGS"; + else + return ret; + warn_msg(WarnDeprecated, "%s:%d: Variable %s is deprecated; use %s instead.", + parser.file.toLatin1().constData(), parser.line_no, + x.toLatin1().constData(), ret.toLatin1().constData()); return ret; } @@ -278,7 +283,7 @@ static QStringList split_arg_list(QString params) return args; } -static QStringList split_value_list(const QString &vals, bool do_semicolon=false) +static QStringList split_value_list(const QString &vals) { QString build; QStringList ret; @@ -289,7 +294,6 @@ static QStringList split_value_list(const QString &vals, bool do_semicolon=false const ushort SINGLEQUOTE = '\''; const ushort DOUBLEQUOTE = '"'; const ushort BACKSLASH = '\\'; - const ushort SEMICOLON = ';'; ushort unicode; const QChar *vals_data = vals.data(); @@ -309,8 +313,7 @@ static QStringList split_value_list(const QString &vals, bool do_semicolon=false ++parens; } - if(!parens && quote.isEmpty() && ((do_semicolon && unicode == SEMICOLON) || - vals_data[x] == Option::field_sep)) { + if(!parens && quote.isEmpty() && (vals_data[x] == Option::field_sep)) { ret << build; build.clear(); } else { @@ -509,69 +512,6 @@ static void qmake_error_msg(const QString &msg) msg.toLatin1().constData()); } -enum isForSymbian_enum { - isForSymbian_NOT_SET = -1, - isForSymbian_FALSE = 0, - isForSymbian_ABLD = 1, - isForSymbian_SBSV2 = 2, -}; - -static isForSymbian_enum isForSymbian_value = isForSymbian_NOT_SET; - -// Checking for symbian build is primarily determined from the qmake spec, -// but if that is not specified, detect if symbian is the default spec -// by checking the MAKEFILE_GENERATOR variable value. -static void init_symbian(const QMap<QString, QStringList>& vars) -{ - if (isForSymbian_value != isForSymbian_NOT_SET) - return; - - QString spec = QFileInfo(Option::mkfile::qmakespec).fileName(); - if (spec.startsWith("symbian-abld", Qt::CaseInsensitive)) { - isForSymbian_value = isForSymbian_ABLD; - } else if (spec.startsWith("symbian-sbsv2", Qt::CaseInsensitive)) { - isForSymbian_value = isForSymbian_SBSV2; - } else { - QStringList generatorList = vars["MAKEFILE_GENERATOR"]; - - if (!generatorList.isEmpty()) { - QString generator = generatorList.first(); - if (generator.startsWith("SYMBIAN_ABLD")) - isForSymbian_value = isForSymbian_ABLD; - else if (generator.startsWith("SYMBIAN_SBSV2")) - isForSymbian_value = isForSymbian_SBSV2; - else - isForSymbian_value = isForSymbian_FALSE; - } else { - isForSymbian_value = isForSymbian_FALSE; - } - } - - // Force recursive on Symbian, as non-recursive is not really a viable option there - if (isForSymbian_value != isForSymbian_FALSE) - Option::recursive = true; -} - -bool isForSymbian() -{ - // If isForSymbian_value has not been initialized explicitly yet, - // call initializer with dummy map to check qmake spec. - if (isForSymbian_value == isForSymbian_NOT_SET) - init_symbian(QMap<QString, QStringList>()); - - return (isForSymbian_value != isForSymbian_FALSE); -} - -bool isForSymbianSbsv2() -{ - // If isForSymbian_value has not been initialized explicitly yet, - // call initializer with dummy map to check qmake spec. - if (isForSymbian_value == isForSymbian_NOT_SET) - init_symbian(QMap<QString, QStringList>()); - - return (isForSymbian_value == isForSymbian_SBSV2); -} - /* 1) environment variable QMAKEFEATURES (as separated by colons) 2) property variable QMAKEFEATURES (as separated by colons) @@ -597,25 +537,15 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) concat << base_concat + QDir::separator() + "macx"; concat << base_concat + QDir::separator() + "unix"; break; + default: // Can't happen, just make the compiler shut up case Option::TARG_UNIX_MODE: - { - if (isForSymbian()) - concat << base_concat + QDir::separator() + "symbian"; - else - concat << base_concat + QDir::separator() + "unix"; - break; - } + concat << base_concat + QDir::separator() + "unix"; + break; case Option::TARG_WIN_MODE: - { - if (isForSymbian()) - concat << base_concat + QDir::separator() + "symbian"; - else - concat << base_concat + QDir::separator() + "win32"; - break; - } - case Option::TARG_MAC9_MODE: - concat << base_concat + QDir::separator() + "mac"; - concat << base_concat + QDir::separator() + "mac9"; + concat << base_concat + QDir::separator() + "win32"; + break; + case Option::TARG_SYMBIAN_MODE: + concat << base_concat + QDir::separator() + "symbian"; break; } concat << base_concat; @@ -629,9 +559,9 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) feature_roots += splitPathList(prop->value("QMAKEFEATURES")); if(!Option::mkfile::cachefile.isEmpty()) { QString path; - int last_slash = Option::mkfile::cachefile.lastIndexOf(Option::dir_sep); + int last_slash = Option::mkfile::cachefile.lastIndexOf(QDir::separator()); if(last_slash != -1) - path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash)); + path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash), false); for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) feature_roots << (path + (*concat_it)); @@ -687,38 +617,6 @@ QStringList qmake_mkspec_paths() return ret; } -class QMakeProjectEnv -{ - QStringList envs; -public: - QMakeProjectEnv() { } - QMakeProjectEnv(QMakeProject *p) { execute(p->variables()); } - QMakeProjectEnv(const QMap<QString, QStringList> &values) { execute(values); } - - void execute(QMakeProject *p) { execute(p->variables()); } - void execute(const QMap<QString, QStringList> &values) { -#ifdef Q_OS_UNIX - for(QMap<QString, QStringList>::ConstIterator it = values.begin(); it != values.end(); ++it) { - const QString var = it.key(), val = it.value().join(" "); - if(!var.startsWith(".")) { - const QString env_var = Option::sysenv_mod + var; - if(!putenv(strdup(QString(env_var + "=" + val).toAscii().data()))) - envs.append(env_var); - } - } -#else - Q_UNUSED(values); -#endif - } - ~QMakeProjectEnv() { -#ifdef Q_OS_UNIX - for(QStringList::ConstIterator it = envs.begin();it != envs.end(); ++it) { - putenv(strdup(QString(*it + "=").toAscii().data())); - } -#endif - } -}; - QMakeProject::~QMakeProject() { if(own_prop) @@ -748,6 +646,7 @@ QMakeProject::init(QMakeProperty *p, const QMap<QString, QStringList> *vars) prop = p; own_prop = false; } + recursive = false; reset(); } @@ -772,6 +671,7 @@ QMakeProject::reset() scope_blocks.push(ScopeBlock()); iterator = 0; function = 0; + backslashWarned = false; } bool @@ -1147,7 +1047,7 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place, int num SKIP_WS(d, d_off, s.length()); QString vals = s.mid(d_off); // vals now contains the space separated list of values int rbraces = vals.count('}'), lbraces = vals.count('{'); - if(scope_blocks.count() > 1 && rbraces - lbraces == 1) { + if(scope_blocks.count() > 1 && rbraces - lbraces == 1 && vals.endsWith('}')) { debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.toLatin1().constData(), parser.line_no, scope_blocks.count()); ScopeBlock sb = scope_blocks.pop(); @@ -1174,7 +1074,7 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place, int num } if(vals.contains('=') && numLines > 1) - warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d", + warn_msg(WarnParser, "Possible accidental line continuation: {%s} at %s:%d", var.toLatin1().constData(), parser.file.toLatin1().constData(), parser.line_no); QStringList &varlist = place[var]; // varlist is the list in the symbol table @@ -1227,7 +1127,7 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place, int num QStringList vallist; { //doVariableReplace(vals, place); - QStringList tmp = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH")); + QStringList tmp = split_value_list(vals); for(int i = 0; i < tmp.size(); ++i) vallist += doVariableReplaceExpand(tmp[i], place); } @@ -1317,8 +1217,7 @@ QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) reset(); const QString oldpwd = qmake_getpwd(); - QString filename = Option::fixPathToLocalOS(file); - doVariableReplace(filename, place); + QString filename = Option::fixPathToLocalOS(file, false); bool ret = false, using_stdin = false; QFile qfile; if(!strcmp(filename.toLatin1(), "-")) { @@ -1362,16 +1261,7 @@ bool QMakeProject::read(uchar cmd) { if(cfile.isEmpty()) { - //find out where qmake (myself) lives - if (!base_vars.contains("QMAKE_QMAKE")) { - if (!Option::qmake_abslocation.isNull()) - base_vars["QMAKE_QMAKE"] = QStringList(Option::qmake_abslocation); - else - base_vars["QMAKE_QMAKE"] = QStringList("qmake"); - } - // hack to get the Option stuff in there - base_vars["QMAKE_EXT_OBJ"] = QStringList(Option::obj_ext); base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; base_vars["QMAKE_EXT_C"] = Option::c_ext; base_vars["QMAKE_EXT_H"] = Option::h_ext; @@ -1457,16 +1347,12 @@ QMakeProject::read(uchar cmd) while(qmakespec.endsWith(QString(QChar(QDir::separator())))) qmakespec.truncate(qmakespec.length()-1); QString spec = qmakespec + QDir::separator() + "qmake.conf"; - if(!QFile::exists(spec) && - QFile::exists(qmakespec + QDir::separator() + "tmake.conf")) - spec = qmakespec + QDir::separator() + "tmake.conf"; debug_msg(1, "QMAKESPEC conf: reading %s", spec.toLatin1().constData()); if(!read(spec, base_vars)) { fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.toLatin1().constData()); return false; } - - init_symbian(base_vars); + validateModes(); if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.toLatin1().constData()); @@ -1520,16 +1406,6 @@ QMakeProject::read(uchar cmd) return false; } - if(cmd & ReadPostFiles) { // parse post files - const QStringList l = vars["QMAKE_POST_INCLUDE_FILES"]; - for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { - if(read((*it), vars)) { - if(vars["QMAKE_INTERNAL_INCLUDED_FILES"].indexOf((*it)) == -1) - vars["QMAKE_INTERNAL_INCLUDED_FILES"].append((*it)); - } - } - } - if(cmd & ReadCmdLine) { parser.file = "(internal)"; parser.from_file = false; @@ -1590,6 +1466,46 @@ QMakeProject::read(uchar cmd) return true; } +void QMakeProject::validateModes() +{ + if (Option::host_mode == Option::HOST_UNKNOWN_MODE + || Option::target_mode == Option::TARG_UNKNOWN_MODE) { + Option::HOST_MODE host_mode; + Option::TARG_MODE target_mode; + const QStringList &gen = base_vars.value("MAKEFILE_GENERATOR"); + if (gen.isEmpty()) { + fprintf(stderr, "%s:%d: Using OS scope before setting MAKEFILE_GENERATOR\n", + parser.file.toLatin1().constData(), parser.line_no); + } else if (MetaMakefileGenerator::modesForGenerator(gen.first(), + &host_mode, &target_mode)) { + if (Option::host_mode == Option::HOST_UNKNOWN_MODE) { + Option::host_mode = host_mode; + Option::applyHostMode(); + } + + if (Option::target_mode == Option::TARG_UNKNOWN_MODE) { + const QStringList &tgt = base_vars.value("TARGET_PLATFORM"); + if (!tgt.isEmpty()) { + const QString &os = tgt.first(); + if (os == "unix") + Option::target_mode = Option::TARG_UNIX_MODE; + else if (os == "macx") + Option::target_mode = Option::TARG_MACX_MODE; + else if (os == "symbian") + Option::target_mode = Option::TARG_SYMBIAN_MODE; + else if (os == "win32") + Option::target_mode = Option::TARG_WIN_MODE; + else + fprintf(stderr, "Unknown target platform specified: %s\n", + os.toLatin1().constData()); + } else { + Option::target_mode = target_mode; + } + } + } + } +} + bool QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QStringList> *place) { @@ -1602,31 +1518,26 @@ QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QString else if(x == "false") return false; + if (x == "unix") { + validateModes(); + return Option::target_mode == Option::TARG_UNIX_MODE + || Option::target_mode == Option::TARG_MACX_MODE + || Option::target_mode == Option::TARG_SYMBIAN_MODE; + } else if (x == "macx" || x == "mac") { + validateModes(); + return Option::target_mode == Option::TARG_MACX_MODE; + } else if (x == "symbian") { + validateModes(); + return Option::target_mode == Option::TARG_SYMBIAN_MODE; + } else if (x == "win32") { + validateModes(); + return Option::target_mode == Option::TARG_WIN_MODE; + } + + //mkspecs static QString spec; if(spec.isEmpty()) spec = QFileInfo(Option::mkfile::qmakespec).fileName(); - - // Symbian is an exception to how scopes are resolved. Since we do not - // have a separate target mode for Symbian, but we expect the scope to resolve - // on other platforms we base it entirely on the mkspec. This means that - // using a mkspec starting with 'symbian*' will resolve both the 'symbian' - // and the 'unix' (because of Open C) scopes to true. - if(isForSymbian() && (x == "symbian" || x == "unix")) - return true; - - //mkspecs - if((Option::target_mode == Option::TARG_MACX_MODE || - Option::target_mode == Option::TARG_UNIX_MODE) && x == "unix") - return !isForSymbian(); - else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx") - return !isForSymbian(); - else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9") - return !isForSymbian(); - else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) && - x == "mac") - return !isForSymbian(); - else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32") - return !isForSymbian(); QRegExp re(x, Qt::CaseSensitive, QRegExp::Wildcard); if((regex && re.exactMatch(spec)) || (!regex && spec == x)) return true; @@ -1718,7 +1629,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QMap<QString, QStringL if(file.indexOf(Option::dir_sep) == -1 || !QFile::exists(file)) { static QStringList *feature_roots = 0; if(!feature_roots) { - init_symbian(base_vars); + validateModes(); feature_roots = new QStringList(qmake_feature_paths(prop)); qmakeAddCacheClear(qmakeDeleteCacheClear_QStringList, (void**)&feature_roots); } @@ -1799,7 +1710,6 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QMap<QString, QStringL fprintf(stderr, "Cannot find directory: %s\n", file.left(di).toLatin1().constData()); return IncludeFailure; } - file = file.right(file.length() - di - 1); } bool parsed = false; parser_info pi = parser; @@ -1819,9 +1729,9 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QMap<QString, QStringL if(proj.doProjectInclude("default_pre", IncludeFlagFeature, proj.variables()) == IncludeNoExist) proj.doProjectInclude("default", IncludeFlagFeature, proj.variables()); #endif - parsed = proj.read(file, proj.variables()); + parsed = proj.read(file, proj.variables()); // parse just that file (fromfile, infile) } else { - parsed = proj.read(file); + parsed = proj.read(file); // parse all aux files (load/include into) } place = proj.variables(); } else { @@ -1887,7 +1797,11 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list, for(int i = 0; i < args_list.size(); ++i) args += args_list[i].join(QString(Option::field_sep)); - ExpandFunc func_t = qmake_expandFunctions().value(func.toLower()); + QString lfunc = func.toLower(); + if (!lfunc.isSharedWith(func)) + warn_msg(WarnDeprecated, "%s:%d: Using uppercased builtin functions is deprecated.", + parser.file.toLatin1().constData(), parser.line_no); + ExpandFunc func_t = qmake_expandFunctions().value(lfunc); debug_msg(1, "Running project expand: %s(%s) [%d]", func.toLatin1().constData(), args.join("::").toLatin1().constData(), func_t); @@ -2141,7 +2055,6 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list, fprintf(stderr, "%s:%d system(execut) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); } else { - QMakeProjectEnv env(place); char buff[256]; bool singleLine = true; if(args.count() > 1) @@ -2267,7 +2180,7 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list, if(args.count() != 1) { fprintf(stderr, "%s:%d prompt(question) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); - } else if(projectFile() == "-") { + } else if(pfile == "-") { fprintf(stderr, "%s:%d prompt(question) cannot be used when '-o -' is used.\n", parser.file.toLatin1().constData(), parser.line_no); } else { @@ -2301,8 +2214,7 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list, fprintf(stderr, "%s:%d: size(var) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); } else { - //QString target = args[0]; - int size = values(args[0]).size(); + int size = values(args[0], place).size(); ret += QString::number(size); } break; } @@ -2428,12 +2340,9 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QMap<QSt if(d_off == d_len-1) test += *(d+d_off); if(!test.isEmpty()) { - const bool success = doProjectTest(test, place); - test = ""; - if(or_op) - ret = ret || success; - else - ret = ret && success; + if (or_op != ret) + ret = doProjectTest(test, place); + test.clear(); } if(*(d+d_off) == QLatin1Char(':')) { or_op = false; @@ -2536,8 +2445,7 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QMap<QSt } } return false; } - case T_SYSTEM: { - bool setup_env = true; + case T_SYSTEM: if(args.count() < 1 || args.count() > 2) { fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.toLatin1().constData(), parser.line_no); @@ -2545,13 +2453,11 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QMap<QSt } if(args.count() == 2) { const QString sarg = args[1]; - setup_env = (sarg.toLower() == "true" || sarg.toInt()); + if (sarg.toLower() == "true" || sarg.toInt()) + warn_msg(WarnParser, "%s:%d: system()'s second argument is now hard-wired to false.\n", + parser.file.toLatin1().constData(), parser.line_no); } - QMakeProjectEnv env; - if(setup_env) - env.execute(place); - bool ret = system(args[0].toLatin1().constData()) == 0; - return ret; } + return system(args[0].toLatin1().constData()) == 0; case T_RETURN: if(function_blocks.isEmpty()) { fprintf(stderr, "%s:%d unexpected return()\n", @@ -2566,8 +2472,6 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QMap<QSt case T_BREAK: if(iterator) iterator->cause_break = true; - else if(!scope_blocks.isEmpty()) - scope_blocks.top().ignore = true; else fprintf(stderr, "%s:%d unexpected break()\n", parser.file.toLatin1().constData(), parser.line_no); @@ -2782,6 +2686,21 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QMap<QSt exit(2); #endif return true; } + case T_OPTION: + if (args.count() != 1) { + fprintf(stderr, "%s:%d: option() requires one argument.\n", + parser.file.toLatin1().constData(), parser.line_no); + return false; + } + if (args.first() == "recursive") { + recursive = true; + } else { + fprintf(stderr, "%s:%d: unrecognized option() argument '%s'.\n", + parser.file.toLatin1().constData(), parser.line_no, + args.first().toLatin1().constData()); + return false; + } + return true; default: fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.toLatin1().constData(), parser.line_no, func.toLatin1().constData()); @@ -3004,6 +2923,11 @@ QMakeProject::doVariableReplaceExpand(const QString &str, QMap<QString, QStringL break; } } + if(!escape && !backslashWarned) { + backslashWarned = true; + warn_msg(WarnDeprecated, "%s:%d: Unescaped backslashes are deprecated.", + parser.file.toLatin1().constData(), parser.line_no); + } if(escape || !replaced) unicode =0; } else if(!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { @@ -3081,8 +3005,6 @@ QStringList &QMakeProject::values(const QString &_var, QMap<QString, QStringList QString orig_template = place["TEMPLATE"].first(), real_template; if(!Option::user_template_prefix.isEmpty() && !orig_template.startsWith(Option::user_template_prefix)) real_template = Option::user_template_prefix + orig_template; - if(real_template.endsWith(".t")) - real_template = real_template.left(real_template.length()-2); if(!real_template.isEmpty()) { var = ".BUILTIN." + var; place[var] = QStringList(real_template); @@ -3166,12 +3088,45 @@ QStringList &QMakeProject::values(const QString &_var, QMap<QString, QStringList } else if (var == QLatin1String("QMAKE_DIR_SEP")) { if (place[var].isEmpty()) return values("DIR_SEPARATOR", place); + } else if (var == QLatin1String("QMAKE_EXT_OBJ")) { + if (place[var].isEmpty()) { + var = ".BUILTIN." + var; + place[var] = QStringList(Option::obj_ext); + } + } else if (var == QLatin1String("QMAKE_QMAKE")) { + if (place[var].isEmpty()) + place[var] = QStringList(Option::fixPathToTargetOS( + !Option::qmake_abslocation.isEmpty() + ? Option::qmake_abslocation + : QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake", + false)); } else if (var == QLatin1String("EPOCROOT")) { if (place[var].isEmpty()) place[var] = QStringList(epocRoot()); } +#if defined(Q_OS_WIN32) && defined(Q_CC_MSVC) + else if(var.startsWith(QLatin1String("QMAKE_TARGET."))) { + QString ret, type = var.mid(13); + if(type == "arch") { + QString paths = qgetenv("PATH"); + QString vcBin64 = qgetenv("VCINSTALLDIR").append("\\bin\\amd64"); + QString vcBinX86_64 = qgetenv("VCINSTALLDIR").append("\\bin\\x86_amd64"); + if(paths.contains(vcBin64,Qt::CaseInsensitive) || paths.contains(vcBinX86_64,Qt::CaseInsensitive)) + ret = "x86_64"; + else + ret = "x86"; + } + place[var] = QStringList(ret); + } +#endif //qDebug("REPLACE [%s]->[%s]", qPrintable(var), qPrintable(place[var].join("::"))); return place[var]; } +bool QMakeProject::isEmpty(const QString &v) +{ + QMap<QString, QStringList>::ConstIterator it = vars.constFind(varMap(v)); + return it == vars.constEnd() || it->isEmpty(); +} + QT_END_NAMESPACE diff --git a/qmake/project.h b/qmake/project.h index 1f53bf22ab..1d9ec047f9 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -78,7 +78,9 @@ class QMakeProject FunctionBlock *function; QMap<QString, FunctionBlock*> testFunctions, replaceFunctions; + bool recursive; bool own_prop; + bool backslashWarned; QString pfile, cfile; QMakeProperty *prop; void reset(); @@ -105,6 +107,7 @@ class QMakeProject QStringList doVariableReplaceExpand(const QString &str, QMap<QString, QStringList> &place, bool *ok=0); void init(QMakeProperty *, const QMap<QString, QStringList> *); QStringList &values(const QString &v, QMap<QString, QStringList> &place); + void validateModes(); public: QMakeProject() { init(0, 0); } @@ -115,7 +118,7 @@ public: ~QMakeProject(); enum { ReadCache=0x01, ReadConf=0x02, ReadCmdLine=0x04, ReadProFile=0x08, - ReadPostFiles=0x10, ReadFeatures=0x20, ReadConfigs=0x40, ReadAll=0xFF }; + ReadFeatures=0x20, ReadConfigs=0x40, ReadAll=0xFF }; inline bool parse(const QString &text) { return parse(text, vars); } bool read(const QString &project, uchar cmd=ReadAll); bool read(uchar cmd=ReadAll); @@ -124,7 +127,6 @@ public: QStringList userTestFunctions() { return testFunctions.keys(); } QString projectFile(); - QString configFile(); inline QMakeProperty *properties() { return prop; } bool doProjectTest(QString str, QMap<QString, QStringList> &place); @@ -148,11 +150,13 @@ public: bool isActiveConfig(const QString &x, bool regex=false, QMap<QString, QStringList> *place=NULL); - bool isSet(const QString &v); - bool isEmpty(const QString &v); - QStringList &values(const QString &v); - QString first(const QString &v); - QMap<QString, QStringList> &variables(); + bool isSet(const QString &v); // No compat mapping, no magic variables + bool isEmpty(const QString &v); // With compat mapping, but no magic variables + QStringList &values(const QString &v); // With compat mapping and magic variables + QString first(const QString &v); // ditto + QMap<QString, QStringList> &variables(); // No compat mapping and magic, obviously + + bool isRecursive() const { return recursive; } protected: friend class MakefileGenerator; @@ -169,15 +173,9 @@ inline QString QMakeProject::projectFile() return pfile; } -inline QString QMakeProject::configFile() -{ return cfile; } - inline QStringList &QMakeProject::values(const QString &v) { return values(v, vars); } -inline bool QMakeProject::isEmpty(const QString &v) -{ return !isSet(v) || values(v).isEmpty(); } - inline bool QMakeProject::isSet(const QString &v) { return vars.contains(v); } @@ -192,10 +190,6 @@ inline QString QMakeProject::first(const QString &v) inline QMap<QString, QStringList> &QMakeProject::variables() { return vars; } -// Helper functions needed for Symbian -bool isForSymbian(); -bool isForSymbianSbsv2(); - QT_END_NAMESPACE #endif // PROJECT_H diff --git a/qmake/property.cpp b/qmake/property.cpp index 34368cd206..fde7c6560d 100644 --- a/qmake/property.cpp +++ b/qmake/property.cpp @@ -95,6 +95,8 @@ QMakeProperty::value(QString v, bool just_check) return QLibraryInfo::location(QLibraryInfo::BinariesPath); else if(v == "QT_INSTALL_PLUGINS") return QLibraryInfo::location(QLibraryInfo::PluginsPath); + else if(v == "QT_INSTALL_IMPORTS") + return QLibraryInfo::location(QLibraryInfo::ImportsPath); else if(v == "QT_INSTALL_TRANSLATIONS") return QLibraryInfo::location(QLibraryInfo::TranslationsPath); else if(v == "QT_INSTALL_CONFIGURATION") @@ -104,7 +106,7 @@ QMakeProperty::value(QString v, bool just_check) else if(v == "QT_INSTALL_DEMOS") return QLibraryInfo::location(QLibraryInfo::DemosPath); else if(v == "QMAKE_MKSPECS") - return qmake_mkspec_paths().join(Option::target_mode == Option::TARG_WIN_MODE ? ";" : ":"); + return qmake_mkspec_paths().join(Option::dirlist_sep); else if(v == "QMAKE_VERSION") return qmake_version(); #ifdef QT_VERSION_STR @@ -191,6 +193,7 @@ QMakeProperty::exec() specialProps.append("QT_INSTALL_LIBS"); specialProps.append("QT_INSTALL_BINS"); specialProps.append("QT_INSTALL_PLUGINS"); + specialProps.append("QT_INSTALL_IMPORTS"); specialProps.append("QT_INSTALL_TRANSLATIONS"); specialProps.append("QT_INSTALL_CONFIGURATION"); specialProps.append("QT_INSTALL_EXAMPLES"); diff --git a/qmake/qmake.pri b/qmake/qmake.pri index 8d3a5596e3..36c5d36a83 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -12,8 +12,10 @@ SOURCES += project.cpp property.cpp main.cpp generators/makefile.cpp \ generators/makefiledeps.cpp generators/metamakefile.cpp generators/mac/pbuilder_pbx.cpp \ generators/xmloutput.cpp generators/win32/borland_bmake.cpp \ generators/win32/msvc_nmake.cpp generators/projectgenerator.cpp \ - generators/win32/msvc_dsp.cpp generators/win32/msvc_vcproj.cpp \ - generators/win32/msvc_objectmodel.cpp \ + generators/win32/msvc_vcproj.cpp \ + generators/win32/msvc_vcxproj.cpp \ + generators/win32/msvc_objectmodel.cpp generators/win32/msbuild_objectmodel.cpp \ + generators/symbian/symbiancommon.cpp \ generators/symbian/symmake.cpp \ generators/symbian/symmake_abld.cpp \ generators/symbian/symmake_sbsv2.cpp \ @@ -23,11 +25,13 @@ SOURCES += project.cpp property.cpp main.cpp generators/makefile.cpp \ HEADERS += project.h property.h generators/makefile.h \ generators/unix/unixmake.h meta.h option.h cachekeys.h \ - generators/win32/winmakefile.h generators/projectgenerator.h \ + generators/win32/winmakefile.h generators/win32/mingw_make.h generators/projectgenerator.h \ generators/makefiledeps.h generators/metamakefile.h generators/mac/pbuilder_pbx.h \ generators/xmloutput.h generators/win32/borland_bmake.h generators/win32/msvc_nmake.h \ - generators/win32/msvc_dsp.h generators/win32/msvc_vcproj.h \ - generators/win32/mingw_make.h generators/win32/msvc_objectmodel.h \ + generators/win32/msvc_vcproj.h \ + generators/win32/msvc_vcxproj.h \ + generators/win32/msvc_objectmodel.h generators/win32/msbuild_objectmodel.h \ + generators/symbian/symbiancommon.h \ generators/symbian/symmake.h \ generators/symbian/symmake_abld.h \ generators/symbian/symmake_sbsv2.h \ @@ -131,7 +135,7 @@ bootstrap { #Qt code SOURCES += qfsfileengine_win.cpp qfsfileengine_iterator_win.cpp qsettings_win.cpp \ qsystemlibrary.cpp win32-msvc*:LIBS += ole32.lib advapi32.lib - win32-g++:LIBS += -lole32 -luuid + win32-g++*:LIBS += -lole32 -luuid } qnx { diff --git a/qmake/qmake.pro b/qmake/qmake.pro index f3f9d5386d..b602afa198 100644 --- a/qmake/qmake.pro +++ b/qmake/qmake.pro @@ -19,7 +19,8 @@ VPATH += $$QT_SOURCE_TREE/src/corelib/global \ $$QT_SOURCE_TREE/src/corelib/plugin \ $$QT_SOURCE_TREE/src/corelib/xml \ $$QT_SOURCE_TREE/src/corelib/io -INCPATH += generators \ +INCLUDEPATH += . \ + generators \ generators/unix \ generators/win32 \ generators/mac \ @@ -29,7 +30,7 @@ INCPATH += generators \ $$QT_SOURCE_TREE/qmake VPATH += $$QT_SOURCE_TREE/tools/shared -INCPATH += $$QT_SOURCE_TREE/tools/shared +INCLUDEPATH += $$QT_SOURCE_TREE/tools/shared include(qmake.pri) |