Merge topic 'qt4-autolink-qtmain'

e3b5eb6 Automatically link to the qtmain library when linking to QtCore.
6c8d8af Add the $<TARGET_POLICY> expression
This commit is contained in:
Brad King 2013-01-23 15:11:24 -05:00 committed by CMake Topic Stage
commit a37b0e3ebf
23 changed files with 284 additions and 4 deletions

View File

@ -65,6 +65,12 @@
# is much more flexible, but requires that FindQt4.cmake is executed before
# such an exported dependency file is processed.
#
# Note that if using IMPORTED targets, the qtmain.lib static library is
# automatically linked on Windows. To disable that globally, set the
# QT4_NO_LINK_QTMAIN variable before finding Qt4. To disable that for a
# particular executable, set the QT4_NO_LINK_QTMAIN target property to
# True on the executable.
#
# QT_INCLUDE_DIRS_NO_SYSTEM
# If this variable is set to TRUE, the Qt include directories
# in the QT_USE_FILE will NOT have the SYSTEM keyword set.
@ -1009,7 +1015,14 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
# platform dependent libraries
if(Q_WS_WIN)
_QT4_ADJUST_LIB_VARS(qtmain)
_QT4_ADJUST_LIB_VARS(QAxServer)
set_property(TARGET Qt4::QAxServer PROPERTY
INTERFACE_QT4_NO_LINK_QTMAIN ON
)
set_property(TARGET Qt4::QAxServer APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN)
_QT4_ADJUST_LIB_VARS(QAxContainer)
endif()
@ -1049,6 +1062,21 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
_qt4_add_target_private_depends(phonon DBus)
endif()
if (WIN32 AND NOT QT4_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:QT4_NO_LINK_QTMAIN>>>)
set(_isPolicyNEW $<TARGET_POLICY:CMP0020>)
set_property(TARGET Qt4::QtCore APPEND PROPERTY
IMPORTED_LINK_INTERFACE_LIBRARIES
$<$<AND:${_isExe},${_isWin32},${_isNotExcluded},${_isPolicyNEW}>:Qt4::qtmain>
)
unset(_isExe)
unset(_isWin32)
unset(_isNotExcluded)
unset(_isPolicyNEW)
endif()
#######################################
#
# Check the executables of Qt

View File

@ -50,6 +50,10 @@
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
"on the target tgt. Note that tgt is not added as a dependency of\n" \
"the target this expression is evaluated on.\n" \
" $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
"the 'head' target was created, else '0'. If the policy was not " \
"set, the warning message for the policy will be emitted. This " \
"generator expression only works for a subset of policies.\n" \
"Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \

View File

@ -508,6 +508,105 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} targetNameNode;
//----------------------------------------------------------------------------
static const char* targetPolicyWhitelist[] = {
"CMP0003"
, "CMP0004"
, "CMP0008"
, "CMP0020"
};
cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
{
#define RETURN_POLICY(POLICY) \
if (strcmp(policy, #POLICY) == 0) \
{ \
return tgt->GetPolicyStatus ## POLICY (); \
} \
RETURN_POLICY(CMP0003)
RETURN_POLICY(CMP0004)
RETURN_POLICY(CMP0008)
RETURN_POLICY(CMP0020)
#undef RETURN_POLICY
assert("!Unreachable code. Not a valid policy");
return cmPolicies::WARN;
}
cmPolicies::PolicyID policyForString(const char *policy_id)
{
#define RETURN_POLICY_ID(POLICY_ID) \
if (strcmp(policy_id, #POLICY_ID) == 0) \
{ \
return cmPolicies:: POLICY_ID; \
} \
RETURN_POLICY_ID(CMP0003)
RETURN_POLICY_ID(CMP0004)
RETURN_POLICY_ID(CMP0008)
RETURN_POLICY_ID(CMP0020)
#undef RETURN_POLICY_ID
assert("!Unreachable code. Not a valid policy");
return cmPolicies::CMP0002;
}
//----------------------------------------------------------------------------
static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
TargetPolicyNode() {}
virtual int NumExpectedParameters() const { return 1; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context ,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *) const
{
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with targets. It may not "
"be used with add_custom_command.");
return std::string();
}
for (size_t i = 0;
i < (sizeof(targetPolicyWhitelist) /
sizeof(*targetPolicyWhitelist));
++i)
{
const char *policy = targetPolicyWhitelist[i];
if (parameters.front() == policy)
{
cmMakefile *mf = context->HeadTarget->GetMakefile();
switch(statusForTarget(context->HeadTarget, policy))
{
case cmPolicies::WARN:
mf->IssueMessage(cmake::AUTHOR_WARNING,
mf->GetPolicies()->
GetPolicyWarning(policyForString(policy)));
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::OLD:
return "0";
case cmPolicies::NEW:
return "1";
}
}
}
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with a limited number of "
"policies. Currently it may be used with policies CMP0003, CMP0004, "
"CMP0008 and CMP0020."
);
return std::string();
}
} targetPolicyNode;
//----------------------------------------------------------------------------
template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator
@ -735,6 +834,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetPropertyNode;
else if (identifier == "TARGET_NAME")
return &targetNameNode;
else if (identifier == "TARGET_POLICY")
return &targetPolicyNode;
else if (identifier == "BUILD_INTERFACE")
return &buildInterfaceNode;
else if (identifier == "INSTALL_INTERFACE")

View File

@ -508,6 +508,27 @@ cmPolicies::cmPolicies()
"for strict compatibility. "
"The NEW behavior for this policy is to leave the values untouched.",
2,8,11,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0020, "CMP0020",
"Automatically link Qt executables to qtmain target on Windows.",
"CMake 2.8.10 and lower required users of Qt to always specify a link "
"dependency to the qtmain.lib static library manually on Windows. CMake "
"2.8.11 gained the ability to evaluate generator expressions while "
"determining the link dependencies from IMPORTED targets. This allows "
"CMake itself to automatically link executables which link to Qt to the "
"qtmain.lib library when using IMPORTED Qt targets. For applications "
"already linking to qtmain.lib, this should have little impact. For "
"applications which supply their own alternative WinMain implementation "
"and for applications which use the QAxServer library, this automatic "
"linking will need to be disabled as per the documentation."
"\n"
"The OLD behavior for this policy is not to link executables to "
"qtmain.lib automatically when they link to the QtCore IMPORTED"
"target. "
"The NEW behavior for this policy is to link executables to "
"qtmain.lib automatically when they link to QtCore IMPORTED target.",
2,8,11,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()

View File

@ -69,6 +69,7 @@ public:
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead.
CMP0019, ///< No variable re-expansion in include and link info
CMP0020, ///< Automatically link Qt executables to qtmain target
/** \brief Always the last entry.
*

View File

@ -145,6 +145,7 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0003 = cmPolicies::WARN;
this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN;
this->PolicyStatusCMP0020 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
@ -1499,6 +1500,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
this->PolicyStatusCMP0020 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
}
//----------------------------------------------------------------------------

View File

@ -102,6 +102,10 @@ public:
cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
{ return this->PolicyStatusCMP0008; }
/** Get the status of policy CMP0020 when the target was created. */
cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const
{ return this->PolicyStatusCMP0020; }
/**
* Get the list of the custom commands for this target
*/
@ -658,6 +662,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0003;
cmPolicies::PolicyStatus PolicyStatusCMP0004;
cmPolicies::PolicyStatus PolicyStatusCMP0008;
cmPolicies::PolicyStatus PolicyStatusCMP0020;
// Internal representation details.
friend class cmTargetInternals;

View File

@ -2,15 +2,16 @@ cmake_minimum_required(VERSION 2.8)
project(Qt4Targets)
cmake_policy(SET CMP0020 NEW)
find_package(Qt4 REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(Qt4Targets WIN32 main.cpp)
target_link_libraries(Qt4Targets Qt4::QtGui)
if (WIN32)
target_link_libraries(Qt4Targets Qt4::qtmain)
endif()
set_property(TARGET Qt4Targets APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
@ -19,3 +20,21 @@ set_property(TARGET Qt4Targets APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
)
if (WIN32)
if (TARGET Qt4::QAxServer)
add_executable(activeqtexe WIN32 activeqtexe.cpp)
set_property(TARGET activeqtexe PROPERTY QT4_NO_LINK_QTMAIN ON)
target_link_libraries(activeqtexe Qt4::QAxServer Qt4::QtGui)
set_property(TARGET activeqtexe APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET activeqtexe APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_COMPILE_DEFINITIONS>
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
)
endif()
endif()

View File

@ -0,0 +1,36 @@
#include <QApplication>
#ifndef QT_QAXSERVER_LIB
#error Expected QT_QAXSERVER_LIB
#endif
#include <QAxFactory>
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject(QObject *parent = 0)
: QObject(parent)
{
}
};
QAXFACTORY_DEFAULT(MyObject,
"{4dc3f340-a6f7-44e4-a79b-3e9217685fbd}",
"{9ee49617-7d5c-441a-b833-4b068d41d751}",
"{13eca64b-ee2a-4f3c-aa04-5d9d975779a7}",
"{ce947ee3-0403-4fdc-895a-4fe779344b46}",
"{8de435ce-8d2a-46ac-b3b3-cb800d0547c7}");
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QAxFactory::isServer();
return app.exec();
}
#include "activeqtexe.moc"

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "foo" links to item " bar " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 NEW)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
target_link_libraries(foo "$<1: bar >")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "bat" links to item " bar " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 OLD)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
add_library(bing SHARED empty.cpp)
add_library(bung SHARED empty.cpp)
cmake_policy(SET CMP0004 NEW)
add_library(bat SHARED empty.cpp)
target_link_libraries(foo "$<1: bar >")
target_link_libraries(bing "$<$<NOT:$<TARGET_POLICY:CMP0004>>: bar >")
target_link_libraries(bung "$<$<TARGET_POLICY:CMP0004>: bar >")
# The line below causes the error because the policy is NEW when bat
# is created.
target_link_libraries(bat "$<1: bar >")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "foo" links to item " bat " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 NEW)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
add_library(bat SHARED empty.cpp)
# The negation here avoids the error.
target_link_libraries(foo "$<$<NOT:$<TARGET_POLICY:CMP0004>>: bar >")
# The below line causes the error.
target_link_libraries(foo "$<$<TARGET_POLICY:CMP0004>: bat >")

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0004-OLD)
run_cmake(CMP0004-NEW)
run_cmake(CMP0004-policy-genex)

View File

View File

@ -60,6 +60,7 @@ add_RunCMake_test(find_package)
add_RunCMake_test(include)
add_RunCMake_test(include_directories)
add_RunCMake_test(list)
add_RunCMake_test(CMP0004)
if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
add_RunCMake_test(include_external_msproject)