Qt: Detect in the .pro file if compiling on 32 bit or 64 bit platform

QtLogo-CodeLess

Couple of months earlier I wrote how to compile Qt projects (.pro files) from command line both on OS X  and Windows. Basically it comes down to calling qmake executable and passing path to your .pro file and path to make spec file for specific compiler. It goes something like this:

C:\QT5_build\bin\qmake.exe [Path to your .pro file] 
-r spec C:\QT5_build\mkspecs\win32-msvc2010

I am using shared .pri configuration files which I later include in my .pro files to have consistent settings across different project. In my base .pri settings files I define where are shared libraries, include files, platform specific compiler flags.

One of the things I want to control is where should output go, namely DESTDIR. I wanted to for my 32 bit builds to land in Output folder and 64 bit in Outputx64, both on Windows and OS X. Here is my shared configuration .pri file:

BUILD_TARGET = SimpleProjectName

win32{
	PROJECT_FOLDER = ..\\..
}
else{
	PROJECT_FOLDER = ../..
}


macx-clang{
    OUTPUT_FOLDER = $$PROJECT_FOLDER/Outputx64
}

macx-clang-32{
    OUTPUT_FOLDER = $$PROJECT_FOLDER/Output
}

win32{
	SOURCE_FOLDER = $$PROJECT_FOLDER\\Source
	OUTPUT_FOLDER = $$PROJECT_FOLDER\\Output$$(Platform)
	TEMP_FOLDER =   $$OUTPUT_FOLDER\\Temp
	MODULE_TEMP_FOLDER = $$TEMP_FOLDER\\$$BUILD_TARGET
	GENERATED_FOLDER = $$OUTPUT_FOLDER\\Generated
	MODULE_GENERATED_FOLDER = $$MODULE_TEMP_FOLDER\\Generated
}
else{
	SOURCE_FOLDER = $$PROJECT_FOLDER/Source
	TEMP_FOLDER = $$OUTPUT_FOLDER/Temp
	MODULE_TEMP_FOLDER = $$TEMP_FOLDER/$$BUILD_TARGET
	GENERATED_FOLDER = $$OUTPUT_FOLDER/Generated
	MODULE_GENERATED_FOLDER = $$MODULE_TEMP_FOLDER/Generated
}

CONFIG(debug, debug|release): CONFIGURATION = Debug
CONFIG(release, debug|release): CONFIGURATION = Release

win32{
	CONFIGURATION_OUTPUT_FOLDER = $$OUTPUT_FOLDER\\$$CONFIGURATION
	CONFIGURATION_MODULE_TEMP_FOLDER = $$MODULE_TEMP_FOLDER\\$$CONFIGURATION
}
else{
	CONFIGURATION_OUTPUT_FOLDER = $$OUTPUT_FOLDER/$$CONFIGURATION
	CONFIGURATION_MODULE_TEMP_FOLDER = $$MODULE_TEMP_FOLDER/$$CONFIGURATION
}

# set intermediate directories
win32{
	UI_DIR = $$GENERATED_FOLDER\\Qt\\$$BUILD_TARGET
	RCC_DIR = $$CONFIGURATION_MODULE_TEMP_FOLDER
	MOC_DIR = $$MODULE_GENERATED_FOLDER
	OBJECTS_DIR= $$CONFIGURATION_MODULE_TEMP_FOLDER
}
else{
	UI_DIR = $$GENERATED_FOLDER/Qt/$$BUILD_TARGET
	RCC_DIR = $$CONFIGURATION_MODULE_TEMP_FOLDER
	MOC_DIR = $$MODULE_GENERATED_FOLDER
	OBJECTS_DIR= $$CONFIGURATION_MODULE_TEMP_FOLDER
}

DESTDIR = $$CONFIGURATION_OUTPUT_FOLDER

With this configuration my project files are normally under "Source" folder and then I will get to right next to it Output or Outputx64 depending on -arch I am using. Inside Output folder there will be Debug or Release folder, based on configuration I am compiling. Next to Debug and Release there will be folders for Temp and Generated files. Something like this:

build output

Key lines for mac OS X are number 11 and number 15. macx-clang is 64bit build configuration and macx-clang-32 is 32 bit build configuration. On line 21 I set Windows build configuration based on $$(Platform) variable. This will in case of 64 bit build add “x64” to “Output”. This flag works only for windows as far as I know. 

Note: In order to be able to build both 32 and 64 bit executables with Qt on OS X platform Qt must be also compiled for desired architecture.  To be able to build Qt on OS X for 32bit architecture Qt build must be configured with -platform macx-clang-32 flag before calling make command.   For example:

./configure -opensource -confirm-license -platform macx-clang-32 -debug-and-release -no-compile-examples ….

Check if an executable or DLL is build in Release or Debug mode

Recently I ran into problem when I tried to pass std::string and std:wstring types between DLLs. Simply hardcoded const std::string passed from one DLL to another gets completely wrong transmitted. It looks like something with encoding is wrong but it turns out somehow I had compiled those two DLLs with deferent configurations. One was Debug another was Release build. Since I had over 50 executables and libraries, static and dynamic, interlinking with each other I had to find out quickly which ones were build wrong configuration.

.NET offers very nice helper class FileVersionInfo with FileVersionInfo.IsDebug property.

The FileVersionInfo properties are based on version resource information built into the file. Version resources are often built into binary files such as .exe or .dll files; text files do not have version resource information. Version resources are typically specified in a Win32 resource file, or in assembly attributes. The IsDebug property reflects the VS_FF_DEBUG flag value in the file's VS_FIXEDFILEINFO block, which is built from the VERSIONINFO resource in a Win32 resource file.

I’ve wrote very simple C# console application that accepts directory path as input parameter. It iterates trough all .exe, .dll and .lib files and writes out to .txt file if it was build with Debug or Release configuration.

Here very short and simple code listing:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConfigChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            string inputPath = string.Empty;
            if (args.Length == 1 && Directory.Exists(args[0])) 
            {
                inputPath = args[0];    
            }
            else
            {
                Console.WriteLine("Input path does not exist. Check input arguments.");
                return;
            }

            string[] searchExtensions = { ".dll", ".exe", ".lib" };
            var files = Directory
                        .GetFiles(inputPath, "*.*", SearchOption.TopDirectoryOnly)
                        .Where(file=> searchExtensions.Any(ext => file.ToLower().Contains(ext)))
                        .ToList();

            uint releaseCount = 0;
            uint debugCount = 0;
            StreamWriter sw = new StreamWriter("output.txt", false);
            foreach (var file in files)
            {
                FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(file);

                sw.Write(file);
                sw.Write("\t\t");

                if (fileVersionInfo.IsDebug)
                {
                    sw.Write("Debug");
                    debugCount++;
                }
                else
                {
                    sw.Write("Release");
                    releaseCount++;
                }
                sw.Write(Environment.NewLine);
            }
            sw.Write(Environment.NewLine);
            sw.WriteLine("Debug: " + debugCount.ToString());
            sw.WriteLine("Release: " + releaseCount.ToString());
            sw.Flush();
            sw.Close();
            sw.Dispose();

            Console.WriteLine("Output successfully written to: " + new FileInfo("output.txt").FullName);
        }
    }
}

Here is output when we call it with “C:\Windows\System32” parameter for example:

...
C:\Windows\System32\XAudio2_7.dll		Release
C:\Windows\System32\XAudioD2_7.dll		Debug
C:\Windows\System32\xcopy.exe		Release
C:\Windows\System32\xinput1_1.dll		Release
C:\Windows\System32\xinput1_2.dll		Release
C:\Windows\System32\xinput1_3.dll		Release
C:\Windows\System32\XInput9_1_0.dll		Release
C:\Windows\System32\xlive.dll		Release

About me

Bizic Bojan is Freelance Software Development Consultant with focus on C++, Qt and .NET based software solutions development. 

 

Disclaimer:

The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.