zhonghua

C++博客 首页 新随笔 联系 聚合 管理
  72 Posts :: 1 Stories :: 4 Comments :: 0 Trackbacks
可能大家或多或少都在qmake的.pro/.pri文件中见过这种代码

TEMPLATE += fakelib
MY_NAME = $$qtLibraryTarget(dbzhang800)
TEMPLATE -= fakelib

如果真的没见过,或许可以从这儿入手分析与学习Qt Solution对qmake的使用
$$qtLibraryTarget 有什么用

我们知道,在Window下,动态库的 Debug 和 Release 版不能通用,所以要放置在不同的路径下或者取不同的名字。在Qt下,我们经常见到

    QtCore4.dll

    QtCored4.dll

而当我们自己的工程中需要动态库时,要想在兼顾各个平台下,给它取个合适的名字还是有点小小的挑战的。

既然Qt已经能处理自己的动态库,我们不妨直接借用它提供的机制,这便是

$$qtLibraryTarget

    作用:为各个平台下的库生成合适的名字
    位置:$QTDIR/mkspecs/features/qt_functions.prf
    具体代码:

defineReplace(qtLibraryTarget) {
   unset(LIBRARY_NAME)
   LIBRARY_NAME = $$1
   mac:!static:contains(QT_CONFIG, qt_framework) {
      QMAKE_FRAMEWORK_BUNDLE_NAME = $$LIBRARY_NAME
      export(QMAKE_FRAMEWORK_BUNDLE_NAME)
   }
   contains(TEMPLATE, .*lib):CONFIG(debug, debug|release) {
      !debug_and_release|build_pass {
          mac:RET = $$member(LIBRARY_NAME, 0)_debug
              else:win32:RET = $$member(LIBRARY_NAME, 0)d
      }
   }
   isEmpty(RET):RET = $$LIBRARY_NAME
   return($$RET)
}

注:这是Qt4.8下的文件,Qt5.0下与此小有不同。

从这儿你可以看到,在windows下它何时会添加一个d,何时不会。
fakelib 干嘛用的

从前面的代码中,我们看到有这么一句

   contains(TEMPLATE, .*lib)

可是,当构建动态库时,不是TEMPLATE确实就是 lib/vclib这些了么?

恩,构建时没有问题,可是当使用时呢?比如

TEMPLATE = app
SOURCES += main.cpp

LIBS += $$qtLibraryTarget(dbzhang800)

还能工作么?

恩,所以了。就需要随便取一个 xxxxxlib 作为模板来哄骗一下它。
还没结束?

自从认识它以后,一直在自己的程序中大量使用这个东西。但是有一件事情总是让人感觉不爽。

使用它以后:

qmake -tp vc

生成的MSVC的工程文件中,总是不能得到正确库文件的名字(具体一点,就是Debug模式下没有那个d)

自己用也没什么,反正也不是什么大问题。只是没想到解决方案竟是这样

SAVE_TEMPLATE = $$TEMPLATE
TEMPLATE = fakelib
MY_NAME = $$qtLibraryTarget(dbzhang800)
TEMPLATE = $$SAVE_TEMPLATE

原因

当qmake使用了 -tp 选项后,对TEMPLATE处理时,只接受一个值。也就是 += 操作对其无效。

具体一点,位于qmake源码 project.cpp 的3043行

    } else if(var == QLatin1String("TEMPLATE")) {
        if(!Option::user_template.isEmpty()) {
            var = ".BUILTIN.USER." + var;
            place[var] =  QStringList(Option::user_template);
        } else {
            QString orig_template, real_template;
            if(!place[var].isEmpty())
                orig_template = place[var].first();
            real_template = orig_template.isEmpty() ? "app" : orig_template;
            if(!Option::user_template_prefix.isEmpty() && !orig_template.startsWith(Option::user_template_prefix))
                real_template.prepend(Option::user_template_prefix);
            if(real_template != orig_template) {
                var = ".BUILTIN." + var;
                place[var] = QStringList(real_template);
            }
        }
posted on 2012-08-17 14:01 米米 阅读(418) 评论(0)  编辑 收藏 引用 所属分类: qt

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理