[UPDATE]
It seems that protobuf_generate_cpp uses absolute paths.
Invoking protobuf compiler manually specifying relative path seems to generate valid sources.
Manual:
/usr/bin/protoc --cpp_out /home/pp/Projects/SmartHomeManagement/shm-iw/build shmiw/metadata/metadata.proto
produces: (metadata.pb.h)
::DescriptorTable descriptor_table_shmiw_2fmetadata_2fmetadata_2eproto;
Name contains subdirectories
Whereas when compiling by protobuf_generate_cpp from cmake, it invokes protobuf compiler with command:
/usr/bin/protoc --cpp_out /home/pp/Projects/SmartHomeManagement/shm-iw/build -I /home/pp/Projects/SmartHomeManagement/shm-iw/shmiw/metadata /home/pp/Projects/SmartHomeManagement/shm-iw/shmiw/metadata/metadata.proto
which produces "invalid" names that can't be used later on by other packages: (metadata.pb.h)
::DescriptorTable descriptor_table_metadata_2eproto;
I've got some problem with protobuf. I've got 3 proto files. The first one is a proto file that contains an option that all other proto files use. All proto files are organized in the same structure, and each of them belongs to a separate package. I want to generate all .h and .cc files and then put them into one single static library.
Project structure is as follows:
/root-dir
-CMakeLists.txt (1)
-shm-iw/
- CMakeLists.txt (2)
- bci
- CMakeLists.txt (3)
- bci.proto
- icon
- CMakeLists.txt (4)
- icon.proto
- metadata
- CMakeLists.txt (5)
- metadata.proto
Root CMakeLists.txt (1)
cmake_minimum_required(VERSION 3.12)
project(shm-iw CXX)
set(SHM-IW_VERSION 0.1)
find_package(Protobuf REQUIRED)
include_directories(${CMAKE_BINARY_DIR})
set (Protobuf_IMPORT_DIRS ${CMAKE_SOURCE_DIR} )
add_subdirectory(shm-iw)
shm-iw CMakeLists.txt (2)
cmake_minimum_required(VERSION 3.12)
add_subdirectory(metadata)
add_subdirectory(bci)
add_subdirectory(icon)
bci CMakeLists.txt (3)
cmake_minimum_required(VERSION 3.12)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
bci.proto
)
add_library(bci_objlib OBJECT
${PROTO_SRCS}
${PROTO_HDRS}
)
target_link_libraries(bci_objlib metadata_objlib)
add_dependencies(bci_objlib metadata_objlib)
bci.proto
syntax = "proto3";
/* Board Control Interface */
import "shmiw/metadata/metadata.proto"; //Note the path to metadata.proto
package shm.iw.bci;
enum IndicatorType {
Status = 0;
Warning = 1;
Maintenance = 2;
Fault = 3;
}
enum IndicatorState {
SteadyOff = 0;
SteadyOn = 1;
Blink = 2;
};
message GetVisualIndicationReq
{
option (shm.iw.metadata.MESSAGE_NUMBER) = 0x1000101;
IndicatorType indicator = 1;
}
message GetVisualIndicationCfm
{
option (shm.iw.metadata.MESSAGE_NUMBER) = 0x1000102;
IndicatorType indicator = 1;
IndicatorState state = 2;
}
metadata CMakeLists.txt (5)
cmake_minimum_required(VERSION 3.12)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
metadata.proto
)
add_library(metadata_objlib OBJECT
${PROTO_SRCS}
${PROTO_HDRS}
)
metadata.proto
syntax = "proto3";
import "google/protobuf/descriptor.proto";
package shm.iw.metadata;
extend google.protobuf.MessageOptions {
uint32 MESSAGE_NUMBER = 50001;
}
I skipped icon directory as it's almost the same as bci directory, they just have different messages but it's not relevant now.
When I'm compiling I'm getting an error
shm-iw/build/shm-iw/bci/bci.pb.cc:183:6: error: ‘::descriptor_table_shm_2diw_2fmetadata_2fmetadata_2eproto’ has not been declared
183 | &::descriptor_table_shmiw_2fmetadata_2fmetadata_2eproto,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Looking at the metadata.pb.h we've got something like this:
extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_metadata_2eproto;
Let's compare the name of the missing declaration and the declaration generated in metadata.pb.h
metadata.pb.h: descriptor_table_metadata_2eproto
bci.pb.c: descriptor_table_shmiw_2fmetadata_2fmetadata_2eproto
They look very similar to each other, but the second one has a few additional words: shm, iw, metadata, which seem to correspond to import path defined in bci.proto
import "shmiw/metadata/metadata.proto";
What's the reason why it happens? Why does the protobuf compiler not generate the metadata's "decriptor_tabele*" accordingly to the package which is defined in metadata.proto?
Protoc handling of path names is pretty confusing, but here are the basics:
Input file names are separated to include dir and relative path.
Relative path determines the name of the symbols that go into generated files.
Include dir must match a directory given with -I.
If no -I arguments are given, there is always an implicit -I .
Based on this, we can figure out why it works the way it works for you:
Case 1: relative path
/usr/bin/protoc
--cpp_out /home/pp/Projects/SmartHomeManagement/shm-iw/build
shmiw/metadata/metadata.proto
No -I is given, so -I . is assumed. The relative path is shmiw/metadata/metadata.proto, giving the symbol name of descriptor_table_shmiw_2fmetadata_2fmetadata_2eproto. The 2f and 2e stand for / and . which are not valid in symbol names.
Case 2: absolute path
/usr/bin/protoc
--cpp_out /home/pp/Projects/SmartHomeManagement/shm-iw/build
-I /home/pp/Projects/SmartHomeManagement/shm-iw/shmiw/metadata
/home/pp/Projects/SmartHomeManagement/shm-iw/shmiw/metadata/metadata.proto
Now the path relative to -I directory is just metadata.proto. Thus you get descriptor_table_metadata_2eproto as the symbol name.
Case 3: absolute path, but same symbol name as case 1
/usr/bin/protoc
--cpp_out /home/pp/Projects/SmartHomeManagement/shm-iw/build
-I /home/pp/Projects/SmartHomeManagement/shm-iw
/home/pp/Projects/SmartHomeManagement/shm-iw/shmiw/metadata/metadata.proto
After this simple change to -I directory, it will give the same symbol name as in case 1.
Related
I'm using Bazel to compile a Qt application (https://github.com/bbreslauer/qt-bazel-example) that is using shaders defined in a qrc file.
When I'm trying to access the resource file, it is not available (as I did not connect the qrc file to the compilation).
How can I define the qrc file content in the build?
UPDATE
following the response by #ypnos, I'm trying to add a macro to my qt.bzl file. I would like the macro to recieve a list of files as an argument, create the (temporary) qrc file, and run the rcc command.
I am currently struggling with:
running a python script in the bzl file is not as straightforward as I though. It cannot generate a file ("open" is undefined). Is it possible? if yes how (see example below)
even with a given qrc file, I cant get the command to work, I guess i'm doing somthing wrong with the command line arguments but I cant find refrence/manual for that
this is what I got so far(my qt.bzl file)
...
def qt_resource(name,file_list, **kwargs):
## following doesnt work inside the bzl file:
# fid = open('%s.qrc' % name, 'w')
# fid.write("<RCC>\n")
# fid.write("\t<qresource prefix=\"/%s\">\n" % name)
# for x in file_list:
# fid.write("\t\t<file>%s</file>\n" % x)
# fid.write("\t</qresource>\n")
# fid.write("</RCC>\n")
# fid.close()
native.genrule(
name = "%s_res" % name,
outs = ["rcc_%s.cpp" % name],
cmd = "rcc %s.qrc -o $#/rcc_%s.cpp"%(name,name) ,
)
srcs = [":rcc_%s.cpp" % name]
native.cc_library(
name = name,
srcs = srcs,
hdrs = [],
deps = [],
**kwargs
)
It seems the bazel example that you are using does not come with support for qrc (it only does moc and ui files).1
QRC files need to be transformed into C++ sources using rcc and then compiled.2 The concept is similar to the one of .ui files which are converted to headers.
Maybe you can patch qt.bzl to add that functionality.
I am a total newbie to Bazel and trying to add a static library to my build.
Lets say as a simple example say I have the following.
cc_import(
name = "my_test_lib"
static_library = "lib\my_test_lib\test.lib"
hdrs = ["lib\my_test_lib\include\headerA.h",
"lib\my_test_lib\include\headerB.h"]
visibility = ["//visibility:public"],
)
Now this works fine.
However, what if I have a huge number of includes and within the include directory there is a number of subdirectories. Do I have to individually enter each one that my main project depends on, or can I do something like the following to essentially make all headers in this directory / subdirectories available?
hdrs = [ "lib\my_test_lib\include\*"]
[This is a supplement to Sebastian's answer.]
Here's a trick I just learned (from a colleague) to use with cc_import:
Suppose you don't want your headers exposed "naked", but want them all in a subdir prefixed by your library name, so that you refer to them like this:
#include <openjpeg/openjpeg.h>
The first step is to have a directory structure that looks like this:
. <library root>
- include
- openjpeg
- openjpeg.h
- <other header files>
But now if you expose these header files via a glob, e.g., glob(["mylib/include/openjpeg/*.h"]) or some variant like glob(["mylib/include/**/*.h"]) (or even by naming them explicitly!) they're not actually exposed as #include <openjpeg/openjpeg.h> but instead as #include "openjpeg.h" or #include <include/openjpeg/openjpeg.h> or something like that.
The problem is that cc_import unaccountably does not support the includes attribute that cc_library does so you can't just name an include directory.
So, use the standard computer science workaround of adding another level of indirection and use this:
cc_library(name = "openjpeg",
includes = ["include"],
deps = ["openjpeg-internal"],
visibility = ["//visibility:public"],
)
cc_import(name = "openjpeg-internal",
hdrs = glob(["include/**/*.h"]),
static_library = ...,
visibility = ["//visibility:private"],
)
What you need is the glob function.
To use it in your above example, you would do something like this
cc_import(
name = "my_test_lib"
static_library = "lib/my_test_lib/test.lib"
hdrs = glob(["lib/my_test_lib/include/*.h"])
visibility = ["//visibility:public"],
)
which would find all files ending with .h under lib\my_test_lib\include and put them in the hdrs attribute of your cc_import.
There's more information about glob in the Bazel documentation: https://docs.bazel.build/versions/master/be/functions.html#glob
Note: Always use forward slashes on all platforms in Bazel BUILD files (even on Windows).
Multiple glob patterns
It's sometimes useful to put in more than one pattern in the glob, for example like this
cc_import(
...
hdrs = glob([
"lib/my_test_lib/include/*.h",
"lib/my_test_lib/include/*.hpp",
"lib/my_test_lib/public/*.h",
]),
...
)
Combining a glob with a hard coded list of files
Another useful thing is combining globs with hard coded paths. You might have a few files you want in there and then a directory you also want to include. You can do this by using the + operator to concatenate the hard coded list of paths with the glob results like this
cc_import(
...
hdrs = [
"lib/my_test_lib/some_header.h",
] + glob([
"lib/my_test_lib/include/*.h",
]),
...
)
Globbing a directory hierarchy (beware of massive inclusions)
The glob function also support traversing directories and their sub directories when finding files. This can be done using the ** glob pattern. So, to for example grab all .h files in the my_test_lib directory, use this glob
cc_import(
...
hdrs = glob([
"lib/my_test_lib/**/*.h",
]),
...
)
Beware: This will include all files below the specified directory, as expected. This can go out of hand since it's not explicit what files get included. Might be better to stay away from **.
I am starting to use Bazel as my C++ project build system.
However I am stuck with the following problem:
I am in a scenario where I automatically generate the file.hpp file.cpp (literate programming).
To reproduce my problem one can simply use this minimal generator:
-- file.sh --
#!/bin/sh
echo "int foo();" >> file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> file.cpp
My project repo is: (WORKSPACE is an empty file)
├── myLib
│ ├── BUILD
│ └── file.sh
└── WORKSPACE
The BUILD file is
genrule(
name = "tangle_file",
srcs = ["file.sh"],
outs = ["file.cpp","file.hpp"],
cmd = "./$(location file.sh);cp file.cpp $(#D);cp file.hpp $(#D);"
)
cc_library(
name = "file",
srcs = ["file.cpp"],
hdrs = ["file.hpp"],
# deps = [":tangle_file"],
visibility = ["//bin:__pkg__"],
)
I have two problems:
Question (A), dealing with the genrule() part:
The fact that I must use
cmd = "./$(location file.sh);cp file.cpp $(#D);cp file.hpp $(#D);"
is quite mysterious.
My first attempt was:
cmd = "./$(location file.sh)"
However in that case I get the following error:
declared output 'myLib/file.cpp' was not created by genrule. This is probably because the genrule actually didn't create this output, or because the output was a directory and the genrule was run remotely (note that only the contents of declared file outputs are copied from genrules run remotely)
Question (B), dealing with the cc_library() part
I do not know how to make Bazel aware of that the :file target depends on the :tangle_file target.
If I uncomment:
deps = [":tangle_file"],
I get the following error:
in deps attribute of cc_library rule //myLib:file: genrule rule '//myLib:tangle_file' is misplaced here (expected cc_inc_library, cc_library, objc_library, experimental_objc_library or cc_proto_library).
Question (A)
The error that you are seeing is because the genrule cmd is not run inside of its output directory. If you hardcoded bazel-out/local-fastbuild/genfiles/myLib/file.cpp instead of file.cpp in your file.sh script, it would work. However, the recommended approach would be for your script to takes its output directory as an argument.
For example,
genrule(
name = "tangle_file",
srcs = ["file.sh"],
outs = ["file.cpp","file.hpp"],
cmd = "./$(location file.sh) $(#D)"
)
and
#!/bin/sh
echo "int foo();" >> $1/file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> $1/file.cpp
Question (B)
The fact that you have
srcs = ["file.cpp"],
hdrs = ["file.hpp"],
in your cc_library is what tells Bazel that it depends on the genrule, since the genrule creates those files. If you want to make it more explicit, you could use the label syntax, which does the same thing:
srcs = ["//myLib:file.cpp"],
hdrs = ["//myLib:file.hpp"],
I am creating a few C++ libraries in a project (solution in VS terminology) that needs to be used by two other projects. For this I created a FindDQSAnalyticsInfra.cmake file which is as follows:
# DQSAnalyticsInfra
# -----
# Find the path to DQSAnalyticsInfra header files and libraries
#
# DEFINES
# ------
# DQSINFRA_ROOT - Root of the DQSAnalyticsInfra project
# DQSINFRA_INCLUDE_DIR - DQSAnalyticsInfra include directory
# DQSINFRA_LIBRARIES - Libraries required to link DQSAnalyticsInfra
# DQSINFRA_FOUND - Confirmation
set(DQSINFRA_LIBRARIES_LIST Utils Actor gtest)
find_path(DQSINFRA_INCLUDE_DIR Actor/Actor.h Utils/Log.h gtest/gtest/gtest.h
${DQSINFRA_ROOT}/include
)
foreach(search_lib ${DQSINFRA_LIBRARIES_LIST})
find_library(DQSINFRA_LIB NAMES ${search_lib}
PATHS
${DQSINFRA_ROOT}/lib/Release #The problem is here
)
set(DQSINFRA_LIBRARIES ${DQSINFRA_LIBRARIES} ${DQSINFRA_LIB})
if(DQSINFRA_LIB)
unset(DQSINFRA_LIB CACHE)
set(DQSINFRA_FOUND TRUE)
else(DQSINFRA_LIB)
set(DQSINFRA_FOUND FALSE)
break()
endif(DQSINFRA_LIB)
endforeach(search_lib)
if(DQSINFRA_INCLUDE_DIR AND DQSINFRA_LIBRARIES AND DQSINFRA_FOUND)
set(DQSINFRA_FOUND TRUE)
message(STATUS "Found DQSAnalyticsInfra. ")
message(STATUS "Include Path: ${DQSINFRA_INCLUDE_DIR}")
message(STATUS "Libraries ${DQSINFRA_LIBRARIES}")
else(DQSINFRA_INCLUDE_DIR AND DQSINFRA_LIBRARIES AND DQSINFRA_FOUND)
set(DQSINFRA_FOUND FALSE)
message(STATUS "DQSAnalyticsInfra not found.")
endif(DQSINFRA_INCLUDE_DIR AND DQSINFRA_LIBRARIES AND DQSINFRA_FOUND)
mark_as_advanced(DQSINFRA_INCLUDE_DIR DQSINFRA_LIBRARIES)
This file works fine. The issue is that in the find_library command used in this file, I am hardcoding the path as ${DQSINFRA_ROOT}/lib/Release. This mean that I cannot use this file to link to Debug builds (I have to manually change the file to use ${DQSINFRA_ROOT}/lib/Debug). Any idea on how this can be fixed.Thanks.
Use debug and optimized keywords that can be specified for target_link_libraries:
find_library(DQSINFRA_LIB_DEBUG NAMES ${search_lib}
PATHS
${DQSINFRA_ROOT}/lib/Debug
)
find_library(DQSINFRA_LIB_RELEASE NAMES ${search_lib}
PATHS
${DQSINFRA_ROOT}/lib/Release
)
set(DQSINFRA_LIBRARIES optimized ${DQSINFRA_LIB_RELEASE} debug ${DQSINFRA_LIB_DEBUG})
I have been trying to include the latest version of qextserialport into the project I am working on. The project structure is as below:
CameraProject
CameraProject.pro
CameraProject
Headers
Sources
qextserialport
Headers
Sources
My CMake file currently looks like so:
PROJECT(CameraProject)
FIND_PACKAGE(Qt4 REQUIRED)
FIND_LIBRARY(SIMPLONLIB lv.simplon lib)
FIND_LIBRARY(SIMPLONIMGPROC lv.simplon.imgproc lib)
SET(CameraProject_SOURCES include/lv.simplon.class.cpp camera.cpp main.cpp mainwindow.cpp osdep.cpp paint.cpp)
SET(CameraProject_HEADERS include/lv.simplon.class.h camera.h mainwindow.h osdep.h paint.h)
SET(CameraProject_RESOURCES icons.qrc)
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_EXECUTABLE(CameraProject ${CameraProject_SOURCES}
${CameraProject_HEADERS_MOC}
${CameraProject_RESOURCES_RCC})
TARGET_LINK_LIBRARIES(CameraProject ${QT_LIBRARIES} ${SIMPLONLIB} ${SIMPLONIMGPROC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} include QExtSerialPort/src)
And despite including the QextSerialPort files in the Include Directories, I get linker issues being drawn.
EDIT: More information!
Found here is the qextserialport.pri file that is included in CameraProject.pro like so: include(./QExtSerialPort/src/qextserialport.pri)
Should I be making a second CMakeLists file for the qextserialport library placed within the source folder?
Any input would be greatly appreciated, please do not hesitate to request for clarification or any further information.
What did for qxt is to use a cmake finder module instead of directly including the code into my projects. I then built qxt with qmake and let CMake find the libraries it creates.
#############
## basic FindQxt.cmake
## This is an *EXTREMELY BASIC* cmake find/config file for
## those times you have a cmake project and wish to use
## libQxt.
##
## It should be noted that at the time of writing, that
## I (mschnee) have an extremely limited understanding of the
## way Find*.cmake files work, but I have attempted to
## emulate what FindQt4.cmake and a few others do.
##
## To enable a specific component, set your QXT_USE_${modname}:
## SET(QXT_USE_QXTCORE TRUE)
## SET(QXT_USE_QXTGUI FALSE)
## Currently available components:
## QxtCore, QxtGui, QxtNetwork, QxtWeb, QxtSql
## Auto-including directories are enabled with INCLUDE_DIRECTORIES(), but
## can be accessed if necessary via ${QXT_INCLUDE_DIRS}
##
## To add the libraries to your build, TARGET_LINK_LIBRARIES(), such as...
## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QXT_LIBRARIES})
## ...or..
## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QT_LIBRARIES} ${QXT_LIBRARIES})
################### TODO:
## The purpose of this cmake file is to find what components
## exist, regardless of how libQxt was build or configured, thus
## it should search/find all possible options. As I am not aware
## that any module requires anything special to be used, adding all
## modules to ${QXT_MODULES} below should be sufficient.
## Eventually, there should be version numbers, but
## I am still too unfamiliar with cmake to determine how to do
## version checks and comparisons.
## At the moment, this cmake returns a failure if you
## try to use a component that doesn't exist. I don't know how to
## set up warnings.
## It would be nice having a FindQxt.cmake and a UseQxt.cmake
## file like done for Qt - one to check for everything in advance
##############
###### setup
SET(QXT_MODULES QxtGui QxtWeb QxtZeroConf QxtNetwork QxtSql QxtBerkeley QxtCore)
SET(QXT_FOUND_MODULES)
FOREACH(mod ${QXT_MODULES})
STRING(TOUPPER ${mod} U_MOD)
SET(QXT_${U_MOD}_INCLUDE_DIR NOTFOUND)
SET(QXT_${U_MOD}_LIB_DEBUG NOTFOUND)
SET(QXT_${U_MOD}_LIB_RELEASE NOTFOUND)
SET(QXT_FOUND_${U_MOD} FALSE)
ENDFOREACH(mod)
SET(QXT_QXTGUI_DEPENDSON QxtCore)
SET(QXT_QXTWEB_DEPENDSON QxtCore QxtNetwork)
SET(QXT_QXTZEROCONF_DEPENDSON QxtCore QxtNetwork)
SET(QXT_QXTNETWORK_DEPENDSON QxtCore)
SET(QXT_QXTQSQL_DEPENDSON QxtCore)
SET(QXT_QXTBERKELEY_DEPENDSON QxtCore)
FIND_PATH(QXT_DIR libqxt.pro Qxt/include/QxtCore/Qxt)
FIND_PATH(QXT_BINARY_DIR
NAMES QxtCore.dll QxtCored.dll
PATHS
${QXT_DIR}/bin
${QXT_DIR}/Bin
NO_DEFAULT_PATH
)
#SET(QXT_BINARY_DIR "${QXT_DIR}/bin" CACHE PATH "${QXT_DIR}/bin")
FOREACH(mod ${QXT_MODULES})
STRING(TOUPPER ${mod} U_MOD)
FIND_PATH(QXT_${U_MOD}_INCLUDE_DIR ${mod}
PATH_SUFFIXES ${mod} include/${mod} Qxt/include/${mod} include/Qxt/${mod}
PATHS
~/Library/Frameworks/
/Library/Frameworks/
/sw/
/usr/local/
/usr
/opt/local/
/opt/csw
/opt
"C:\\"
"C:\\Program Files\\"
"C:\\Program Files(x86)\\"
${QXT_DIR}
NO_DEFAULT_PATH
)
FIND_LIBRARY(QXT_${U_MOD}_LIB_RELEASE NAME ${mod}
PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib
PATHS
/sw
/usr/local
/usr
/opt/local
/opt/csw
/opt
"C:\\"
"C:\\Program Files"
"C:\\Program Files(x86)"
${QXT_DIR}
NO_DEFAULT_PATH
)
FIND_LIBRARY(QXT_${U_MOD}_LIB_DEBUG NAME ${mod}d
PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib
PATHS
/sw
/usr/local
/usr
/opt/local
/opt/csw
/opt
"C:\\"
"C:\\Program Files"
"C:\\Program Files(x86)"
${QXT_DIR}
NO_DEFAULT_PATH
)
IF (QXT_${U_MOD}_LIB_RELEASE)
SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}")
ENDIF (QXT_${U_MOD}_LIB_RELEASE)
IF (QXT_${U_MOD}_LIB_DEBUG)
SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}")
ENDIF (QXT_${U_MOD}_LIB_DEBUG)
ENDFOREACH(mod)
FOREACH(mod ${QXT_MODULES})
STRING(TOUPPER ${mod} U_MOD)
IF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE)
SET(QXT_FOUND_${U_MOD} TRUE)
ENDIF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE)
ENDFOREACH(mod)
##### find and include
# To use a Qxt Library....
# SET(QXT_FIND_COMPONENTS QxtCore, QxtGui)
# ...and this will do the rest
IF( QXT_FIND_COMPONENTS )
FOREACH( component ${QXT_FIND_COMPONENTS} )
STRING( TOUPPER ${component} _COMPONENT )
SET(QXT_USE_${_COMPONENT}_COMPONENT TRUE)
ENDFOREACH( component )
ENDIF( QXT_FIND_COMPONENTS )
SET(QXT_LIBRARIES "")
SET(QXT_INCLUDE_DIRS "")
# like FindQt4.cmake, in order of dependence
FOREACH( module ${QXT_MODULES} )
STRING(TOUPPER ${module} U_MOD)
IF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD})
IF(QXT_FOUND_${U_MOD})
STRING(REPLACE "QXT" "" qxt_module_def "${U_MOD}")
ADD_DEFINITIONS(-DQXT_${qxt_module_def}_LIB)
SET(QXT_INCLUDE_DIRS ${QXT_INCLUDE_DIRS} ${QXT_${U_MOD}_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${QXT_${U_MOD}_INCLUDE_DIR})
SET(QXT_LIBRARIES ${QXT_LIBRARIES};optimized;${QXT_${U_MOD}_LIB_RELEASE};debug;${QXT_${U_MOD}_LIB_DEBUG})
ELSE(QXT_FOUND_${U_MOD})
MESSAGE("Could not find Qxt Module ${module}")
RETURN()
ENDIF(QXT_FOUND_${U_MOD})
FOREACH(dep QXT_${U_MOD}_DEPENDSON)
SET(QXT_DEPENDS_${dep} TRUE)
ENDFOREACH(dep)
ENDIF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD})
ENDFOREACH(module)
MESSAGE(STATUS "Found Qxt Libraries:${QXT_FOUND_MODULES}")
MESSAGE(STATUS "Include directories:${QXT_INCLUDE_DIRS}")
I put this module in a sub directory of my root project called CMake/Modules and include it into cmake near the top of the root CMakeLists.txt using the following command:
# The following line will add additional finders to CMake without the need to be placed in the CMake install path
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake/Modules)
And finally to have CMake find Qxt
SET(QXT_FIND_COMPONENTS QxtCore, QxtGui)
SET(QXT_USE_QXTCORE TRUE)
FIND_PACKAGE(Qxt REQUIRED)