In this qmake code:
MY_COMPILER = mingw
warning($$MY_COMPILER)
contains(MY_COMPILER, mingw)
{
INCLUDEPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
DEPENDPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
QMAKE_RPATHDIR *= ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
contains(QWT_CONFIG, QwtFramework) {
LIBS += -F../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
}
else {
LIBS += -L../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
}
IPATH = ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
warning(Using MinGW compiler)
}
else {
INCLUDEPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
DEPENDPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
QMAKE_RPATHDIR *= ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
contains(QWT_CONFIG, QwtFramework) {
LIBS += -F../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
}
else {
LIBS += -L../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
}
IPATH = ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
warning(Using Intel compiler)
}
Whatever I define for the variable MY_COMPILER, it keeps taking the first condition, whilst it posts through the warning at line 3 the correct variable I entered.
How can I post a variable and then check whether it's defined?
Any efforts are highly appreciated.
Thanks.
I don't see anything wrong with your code, but you could try it this way instead:
CONFIG += mingw
mingw {
//...
} else {
//...
}
EDIT:
Another thing you could try is have the condition and opening curly bracket in the same line,
if I remember right, that caused some problems in the past.
Then the statement would look like this:
contains(MY_COMPILER, mingw) {
//...
} else {
//...
}
Related
I have a .txt file in QT project, where I store settings parameters for my app. If I read it that way
void MainWindow::ReadApplicationSettings()
{
QFile cfgFile("config.txt");
if(!cfgFile.exists())
{
qDebug() << "Cannot find config file.";
}
else
{
ParseConfigFile(cfgFile);
SetCfg();
}
cfgFile.close();
}
And Parse it:
void MainWindow::ParseConfigFile(QFile &cfgFile)
{
QString line;
if (cfgFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream stream(&cfgFile);
while (!stream.atEnd())
{
line = stream.readLine();
std::istringstream iss(line.toStdString());
std::string id, eq, val;
bool error = false;
if (!(iss >> id))
{
error = true;
}
else if (id[0] == '#')
{
continue;
}
else if (!(iss >> eq >> val >> std::ws) || eq != "=" || iss.get() != EOF)
{
error = true;
}
if (error) { throw std::runtime_error("Parse error"); }
cfgMap[id] = std::stoi(val);
}
}
}
The file exists and when the parsing begin the content of the file is empty
The result of: line = stream.readLine(); is "".
If I add the file like a resource file and opened this way:
QFile cfgFile(":config.txt");
It's working correct, but the problem is that the config file is compiled and when you have to change some value, the project must be rebuild to take effect
I tried to compose the path like that QDir::currentPath + "/config.txt", but not working as well.
Another option is the undocumented feature "file_copies" in Qt 5.6 that you can use like this:
CONFIG += file_copies
configfiles.path = $$OUT_PWD
configfiles.files = $$PWD/config.txt
COPIES += configfiles
Found here: https://stackoverflow.com/a/54162789/6842395
If you don't like this method, that post has some more options to choose.
By the way, loooking at your ParseConfigFile() method seems that your config.txt is a collection of lines with the format: key = value, very similar to a classic INI file. Maybe you could use QSettings third constructor like this:
QSettings settings("config.txt", QSettings::IniFormat);
You can use QMAKE_EXTRA_TARGET in your profile like:
copyfile.commands += $${QMAKE_COPY} $$system_path($$PWD/config.txt) $$system_path($$DESTDIR/)
first.depends = $(first) copyfile
QMAKE_EXTRA_TARGETS += first copyfile
But ensure your $$DESTDIR is correct.
I need to fill pdf form.
To do this I found and use qPDF c++ library.
I added libqpdf.dll.a on fillPdf.pro using :
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dll
INCLUDEPATH += $$PWD/qpdf
DEPENDPATH += $$PWD/qpdf
I also added all includes .h and .hh headers from qpdf library to my project.
But I still have bugs that look like linkage problems :
.o:-1: In function `ZN8reporter8fillTestEPKcS1_S1_':
.cpp:19: erreur : undefined reference to `QPDF::QPDF()'
.cpp:20: erreur : undefined reference to `QPDF::processFile(char const*, char const*)' ^
.cpp:19: erreur : undefined reference to `QPDF::~QPDF()'
collect2.exe:-1: erreur : error: ld returned 1 exit status
summarised code all symbols are recognised by qt creator and i have access to theire classes by clicking on them :
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QUtil.hh>
#include <iostream>
int main(int argc, char* argv[])
{
char* whoami = QUtil::getWhoami(argv[0]);
if (argc != 3)
{
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl;
return 2;
}
char const* infile = argv[1];
char const* outfile = argv[2];
QPDF in;
in.processFile(infile);
int pageno = 0;
std::vector<QPDFObjectHandle> const& pages = in.getAllPages();
for (std::vector<QPDFObjectHandle>::const_iterator iter = pages.begin();
iter != pages.end(); ++iter)
{
std::cout << ++pageno << " ";
QPDFObjectHandle page = *iter;
page.replaceKey(
"/Contents",
QPDFObjectHandle::newStream(&in, "q Q"));
}
QPDFWriter out(in, outfile);
out.write();
return 0;
}
More information :
QPDF WINDOWS Lib : https://sourceforge.net/projects/qpdf/files/qpdf/8.4.0/
includes : https://github.com/qpdf/qpdf/tree/master/include/qpdf
exemple : https://github.com/qpdf/qpdf/blob/master/examples/pdf-set-form-values.cc
I am using qt creator 4.4.0 based on qt 5.9.1 (MSVC 2015, 32bit)
Can someone tell me where am i wrong?
My .pro
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG += qt
QT += core gui
QT += axcontainer
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
SOURCES += main.cpp
HEADERS += \
qpdf/Buffer.hh \
qpdf/BufferInputSource.hh \
qpdf/ClosedFileInputSource.hh \
qpdf/Constants.h \
qpdf/DLL.h \
qpdf/FileInputSource.hh \
qpdf/InputSource.hh \
qpdf/JSON.hh \
qpdf/Pipeline.hh \
qpdf/Pl_Buffer.hh \
qpdf/Pl_Concatenate.hh \
qpdf/Pl_Count.hh \
qpdf/Pl_DCT.hh \
qpdf/Pl_Discard.hh \
qpdf/Pl_Flate.hh \
qpdf/Pl_QPDFTokenizer.hh \
qpdf/Pl_RunLength.hh \
qpdf/Pl_StdioFile.hh \
qpdf/PointerHolder.hh \
qpdf/qpdf-c.h \
qpdf/QPDF.hh \
qpdf/QPDFAcroFormDocumentHelper.hh \
qpdf/QPDFAnnotationObjectHelper.hh \
qpdf/QPDFDocumentHelper.hh \
qpdf/QPDFExc.hh \
qpdf/QPDFFormFieldObjectHelper.hh \
qpdf/QPDFNameTreeObjectHelper.hh \
qpdf/QPDFNumberTreeObjectHelper.hh \
qpdf/QPDFObject.hh \
qpdf/QPDFObjectHandle.hh \
qpdf/QPDFObjectHelper.hh \
qpdf/QPDFObjGen.hh \
qpdf/QPDFOutlineDocumentHelper.hh \
qpdf/QPDFOutlineObjectHelper.hh \
qpdf/QPDFPageDocumentHelper.hh \
qpdf/QPDFPageLabelDocumentHelper.hh \
qpdf/QPDFPageObjectHelper.hh \
qpdf/QPDFSystemError.hh \
qpdf/QPDFTokenizer.hh \
qpdf/QPDFWriter.hh \
qpdf/QPDFXRefEntry.hh \
qpdf/QTC.hh \
qpdf/QUtil.hh \
qpdf/RandomDataProvider.hh \
qpdf/Types.h
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dll
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dllINCLUDEPATH += $$PWD/qpdf
DEPENDPATH += $$PWD/qpdf
I get it working using the configuration bellow :
My.pro :
#-------------------------------------------------
#
# Project created by QtCreator 2019-04-01T16:52:28
#
#-------------------------------------------------
QT += core gui
QT += axcontainer
QT += serialport
CONFIG += c++11 console
CONFIG -= app_bundle
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QTfillpdftest
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
qtfillpdf.cpp
HEADERS += \
qtfillpdf.h\
qpdf/Buffer.hh \
qpdf/BufferInputSource.hh \
qpdf/ClosedFileInputSource.hh \
qpdf/Constants.h \
qpdf/DLL.h \
qpdf/FileInputSource.hh \
qpdf/InputSource.hh \
qpdf/JSON.hh \
qpdf/Pipeline.hh \
qpdf/Pl_Buffer.hh \
qpdf/Pl_Concatenate.hh \
qpdf/Pl_Count.hh \
qpdf/Pl_DCT.hh \
qpdf/Pl_Discard.hh \
qpdf/Pl_Flate.hh \
qpdf/Pl_QPDFTokenizer.hh \
qpdf/Pl_RunLength.hh \
qpdf/Pl_StdioFile.hh \
qpdf/PointerHolder.hh \
qpdf/qpdf-c.h \
qpdf/QPDF.hh \
qpdf/QPDFAcroFormDocumentHelper.hh \
qpdf/QPDFAnnotationObjectHelper.hh \
qpdf/QPDFDocumentHelper.hh \
qpdf/QPDFExc.hh \
qpdf/QPDFFormFieldObjectHelper.hh \
qpdf/QPDFNameTreeObjectHelper.hh \
qpdf/QPDFNumberTreeObjectHelper.hh \
qpdf/QPDFObject.hh \
qpdf/QPDFObjectHandle.hh \
qpdf/QPDFObjectHelper.hh \
qpdf/QPDFObjGen.hh \
qpdf/QPDFOutlineDocumentHelper.hh \
qpdf/QPDFOutlineObjectHelper.hh \
qpdf/QPDFPageDocumentHelper.hh \
qpdf/QPDFPageLabelDocumentHelper.hh \
qpdf/QPDFPageObjectHelper.hh \
qpdf/QPDFSystemError.hh \
qpdf/QPDFTokenizer.hh \
qpdf/QPDFWriter.hh \
qpdf/QPDFXRefEntry.hh \
qpdf/QTC.hh \
qpdf/QUtil.hh \
qpdf/RandomDataProvider.hh \
qpdf/Types.h
FORMS += \
qtfillpdf.ui
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dll
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dll
else:unix: LIBS += -L$$PWD/qpdf/lib/ -llibqpdf.dll
INCLUDEPATH += $$PWD/qpdf
DEPENDPATH += $$PWD/qpdf
Function :
int qtfillpdf::qtfillpdfFile( char const* infilename , char const* outfilename,char const* value )
{
qDebug() << "qtfillpdf : 1 " << value;
// This is a contrived example that just goes through a file page
// by page and sets the value of any text fields it finds to a
// fixed value as given on the command line. The purpose here is
// to illustrate use of the helper classes around interactive
// forms.
QPDF qpdf;
qDebug() << "qtfillpdfFile : 1.1 " << value;
qpdf.processFile(infilename);
std::string nm;
nm= qpdf.getFilename();
qDebug() << "qtfillpdf : 2 " << nm.c_str() ;
// We will iterate through form fields by starting at the page
// level and looking at each field for each page. We could
// also called QPDFAcroFormDocumentHelper::getFormFields to
// iterate at the field level, but doing it as below
// illustrates how we can map from annotations to fields.
QPDFAcroFormDocumentHelper afdh(qpdf);
QPDFPageDocumentHelper pdh(qpdf);
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
qDebug() << "qtfillpdf : 3 " ;
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
pages.begin();
page_iter != pages.end(); ++page_iter)
{
// Get all widget annotations for each page. Widget
// annotations are the ones that contain the details of
// what's in a form field.
std::vector<QPDFAnnotationObjectHelper> annotations =
afdh.getWidgetAnnotationsForPage(*page_iter);
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter = annotations.begin();
annot_iter != annotations.end(); ++annot_iter)
{
// For each annotation, find its associated field. If
// it's a text field, set its value. This will
// automatically update the document to indicate that
// appearance streams need to be regenerated. At the
// time of this writing, qpdf doesn't have any helper
// code to assist with appearance stream generation,
// though there's nothing that prevents it from being
// possible.
//qDebug() << "qtfillpdf : 4 " << annot_iter->getAppearanceState().c_str() ;
QPDFFormFieldObjectHelper ffh =
afdh.getFieldForAnnotation(*annot_iter);
if (ffh.getFieldType() == "/Tx")
{
//qDebug() << "qtfillpdf : 5 " <<ffh.getChoices().front().c_str();
// Set the value. This will automatically set
// /NeedAppearances to true. If you don't want to
// do that, pass false as the second argument. For
// details see comments in
// QPDFFormFieldObjectHelper.hh.
ffh.setV(value);
qDebug() << "OK6" << value << " ffh.getValueAsString() : " <<ffh.getValueAsString().c_str();
}
}
}
// Write out a new file
QPDFWriter w(qpdf, outfilename);
w.setStaticID(true); // for testing only
w.write();
return 3;
}
void qtfillpdf::on_Browse_clicked()
{
///TODO : mettre le liens
QString s_configFileName;
QString outfilename = "OUT.pdf";
QString value="qfiller";
s_configFileName = QFileDialog::getOpenFileName(
this,
tr("Selectfile"),
"", tr("pdf Files (*.pdf)")
);
qDebug() << "File Name : " << s_configFileName ;
qtfillpdfFile(s_configFileName.toStdString().c_str(), outfilename.toStdString().c_str(), value.toStdString().c_str());
qDebug()<< " END_BROWSE :" << s_configFileName ;
}
I'm currently running Bayesian Optimization, written in c++. I use a toolbox call Bayesopt from Ruben Martinez-Cantin (http://rmcantin.bitbucket.org/html/). I'm doing my thesis about Bayesian Optimization (https://en.wikipedia.org/wiki/Bayesian_optimization).
I had previously experimented with this toolbox and I have noticed this week that the code is running a lot slower than I remembered. It's worth mentioning that I did write some code that works with this toolbox.
I decided to try to understand why this was happening and I did witness that the code was running much slower than it should.
To try to understand if it was my code's fault or otherwise, I tried an example that doesn't use any of my code.
Consider the following example:
#include <iostream>
#include <bayesopt.hpp>
class ExampleMichalewicz: public bayesopt::ContinuousModel
{
public:
ExampleMichalewicz(bopt_params par);
double evaluateSample(const vectord& x);
bool checkReachability(const vectord &query) {return true;};
void printOptimal();
private:
double mExp;
};
ExampleMichalewicz::ExampleMichalewicz(bopt_params par):
ContinuousModel(10,par)
{
mExp = 10;
}
double ExampleMichalewicz::evaluateSample(const vectord& x)
{
size_t dim = x.size();
double sum = 0.0;
for(size_t i = 0; i<dim; ++i)
{
double frac = x(i)*x(i)*(i+1);
frac /= M_PI;
sum += std::sin(x(i)) * std::pow(std::sin(frac),2*mExp);
}
return -sum;
}
void ExampleMichalewicz::printOptimal()
{
std::cout << "Solutions: " << std::endl;
std::cout << "f(x)=-1.8013 (n=2)"<< std::endl;
std::cout << "f(x)=-4.687658 (n=5)"<< std::endl;
std::cout << "f(x)=-9.66015 (n=10);" << std::endl;
}
int main(int nargs, char *args[])
{
bopt_params par = initialize_parameters_to_default();
par.n_iterations = 20;
par.n_init_samples = 30;
par.random_seed = 0;
par.verbose_level = 1;
par.noise = 1e-10;
par.kernel.name = "kMaternARD5";
par.crit_name = "cBEI";
par.crit_params[0] = 1;
par.crit_params[1] = 0.1;
par.n_crit_params = 2;
par.epsilon = 0.0;
par.force_jump = 0.000;
par.verbose_level = 1;
par.n_iter_relearn = 1; // Number of samples before relearn kernel
par.init_method = 1; // Sampling method for initial set 1-LHS, 2-Sobol (if available),
par.l_type = L_MCMC; // Type of learning for the kernel params
ExampleMichalewicz michalewicz(par);
vectord result(10);
michalewicz.optimize(result);
std::cout << "Result: " << result << "->"
<< michalewicz.evaluateSample(result) << std::endl;
michalewicz.printOptimal();
return 0;
}
If I compile this example alone, the run time is about 23 seconds.
With this cmake file
PROJECT ( myDemo )
ADD_EXECUTABLE(myDemo ./main.cpp)
find_package( Boost REQUIRED )
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
else(Boost_FOUND)
find_library(Boost boost PATHS /opt/local/lib)
include_directories(${Boost_LIBRARY_PATH})
endif()
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories("../bayesopt/include")
include_directories("../bayesopt/utils")
set(CMAKE_CXX_FLAGS " -Wall -std=c++11 -lpthread -Wno-unused-local-typedefs -DNDEBUG -DBOOST_UBLAS_NDEBUG")
target_link_libraries(myDemo libbayesopt.a libnlopt.a)
Now consider the same main example, but where I add three additional files to my cmake project (without including them in main.cpp). These three files are subpart of all my code.
PROJECT ( myDemo )
ADD_EXECUTABLE(myDemo ./iCubSimulator.cpp ./src/DatasetDist.cpp ./src/MeanModelDist.cpp ./src/TGPNode.cpp)
find_package( Boost REQUIRED )
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
else(Boost_FOUND)
find_library(Boost boost PATHS /opt/local/lib)
include_directories(${Boost_LIBRARY_PATH})
endif()
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories("../bayesopt/include")
include_directories("../bayesopt/utils")
set(CMAKE_CXX_FLAGS " -Wall -std=c++11 -lpthread -Wno-unused-local-typedefs -DNDEBUG -DBOOST_UBLAS_NDEBUG")
target_link_libraries(myDemo libbayesopt.a libnlopt.a)
This time, the run time is about 3 minutes. This is critical in my work since if I increase par.n_iterations it tends to get much worse.
I further arrived at the conclusion that if I comment a line in TGPNode.cpp
utils::cholesky_decompose(K,L); (NOTICE THAT THIS LINE IS NEVER CALLED).
I get the 23 seconds. This function belongs to a file: ublas_cholesky.hpp, from the bayesopt toolbox.
It is also important to note that the same function is also called within the toolbox code. This line is not commented and it runs during michalewicz.optimize(result);.
Does anyone have any ideia why this is happening? It would be a great help if anyone has some insight about the subject.
Greatly appreciated.
Kindly, José Nogueira
It's not gonna return.
It's going to infinitely recurse (to a stack overflow).
Here's what the code reads like:
bopt_params initialize_parameters_to_default(void)
{
bayesopt::Parameters par;
return par.generate_bopt_params();
And generate_bopt_params:
bopt_params Parameters::generate_bopt_params(){
bopt_params c_params = initialize_parameters_to_default();
It looks like someone tried to remove code duplication without actually testing things. At all. You could reinstate the commented out body of the first function
I have the following bakefile (WinSparkle.bkl)
toolsets = vs2008 vs2010 vs2012 vs2013;
if ( $toolset == vs2008 )
SUFFIX = "";
if ( $toolset == vs2010 )
SUFFIX = "-2010";
if ( $toolset == vs2012 )
SUFFIX = "-2012";
if ( $toolset == vs2013 )
SUFFIX = "-2013";
vs2008.solutionfile = WinSparkle$(SUFFIX).sln;
vs2010.solutionfile = WinSparkle$(SUFFIX).sln;
vs2012.solutionfile = WinSparkle$(SUFFIX).sln;
vs2013.solutionfile = WinSparkle$(SUFFIX).sln;
// Common settings:
win32-crt-linkage = static;
archs = x86 x86_64;
defines += _CRT_SECURE_NO_WARNINGS;
// Build binaries compatible with Windows XP (SP3) -- it's still useful for
// installer stuff like WinSparkle.dll
vs2012.option.Configuration.PlatformToolset = v110_xp;
vs2013.option.Configuration.PlatformToolset = v120_xp;
if ( $(config) == Release ) {
vs2008.option.VCCLCompilerTool.Optimization = 1;
vs2008.option.VCCLCompilerTool.FavorSizeOrSpeed = 2;
vs2008.option.VCCLCompilerTool.WholeProgramOptimization = true;
vs2008.option.VCCLCompilerTool.StringPooling = true;
vs2008.option.VCLinkerTool.LinkTimeCodeGeneration = 1;
vs2010.option.Configuration.WholeProgramOptimization = true;
vs2010.option.ClCompile.Optimization = MinSpace;
vs2010.option.ClCompile.FavorSizeOrSpeed = Size;
vs2010.option.ClCompile.WholeProgramOptimization = true;
vs2010.option.ClCompile.StringPooling = true;
vs2010.option.ClCompile.FunctionLevelLinking = true;
vs2010.option.Link.OptimizeReferences = true;
vs2010.option.Link.EnableCOMDATFolding = true;
vs2010.option.Link.LinkTimeCodeGeneration = UseLinkTimeCodeGeneration;
vs2012.option.Configuration.WholeProgramOptimization = true;
vs2012.option.ClCompile.Optimization = MinSpace;
vs2012.option.ClCompile.FavorSizeOrSpeed = Size;
vs2012.option.ClCompile.WholeProgramOptimization = true;
vs2012.option.ClCompile.StringPooling = true;
vs2012.option.ClCompile.FunctionLevelLinking = true;
vs2012.option.Link.OptimizeReferences = true;
vs2012.option.Link.EnableCOMDATFolding = true;
vs2012.option.Link.LinkTimeCodeGeneration = UseLinkTimeCodeGeneration;
vs2013.option.Configuration.WholeProgramOptimization = true;
vs2013.option.ClCompile.Optimization = MinSpace;
vs2013.option.ClCompile.FavorSizeOrSpeed = Size;
vs2013.option.ClCompile.WholeProgramOptimization = true;
vs2013.option.ClCompile.StringPooling = true;
vs2013.option.ClCompile.FunctionLevelLinking = true;
vs2013.option.Link.OptimizeReferences = true;
vs2013.option.Link.EnableCOMDATFolding = true;
vs2013.option.Link.LinkTimeCodeGeneration = UseLinkTimeCodeGeneration;
}
// 3rd party library dependencies:
submodule 3rdparty/dependencies.bkl;
shared-library WinSparkle {
vs2008.projectfile = $(id)$(SUFFIX).vcproj;
vs2010.projectfile = $(id)$(SUFFIX).vcxproj;
vs2012.projectfile = $(id)$(SUFFIX).vcxproj;
vs2013.projectfile = $(id)$(SUFFIX).vcxproj;
defines += XML_STATIC;
includedirs += 3rdparty/expat/lib;
deps += WinSparkle_expat;
includedirs += 3rdparty/wxWidgets_setup_h 3rdparty/wxWidgets/include;
deps += WinSparkle_wx;
libs += comctl32 kernel32 user32 comctl32 rpcrt4 version wininet;
defines += BUILDING_WIN_SPARKLE;
// Public API headers:
headers {
include/winsparkle.h
include/winsparkle-version.h
}
includedirs += include;
// Private headers:
headers {
src/appcast.h
src/appcontroller.h
src/download.h
src/error.h
src/settings.h
src/threads.h
src/ui.h
src/updatechecker.h
src/updatedownloader.h
src/utils.h
}
sources {
src/appcast.cpp
src/appcontroller.cpp
src/dll_api.cpp
src/dllmain.cpp
src/download.cpp
src/error.cpp
src/settings.cpp
src/threads.cpp
src/ui.cpp
src/updatechecker.cpp
src/updatedownloader.cpp
src/winsparkle.rc
}
}
submodule examples/examples.bkl;
I downloaded bakefile for windows and installed it. Then I did the following
C:\winsparkle>bakefile -f msvc WinSparkle.bkl
file:///C:/winsparkle/WinSparkle.bkl:2:
parser
error :
Start tag expected, '<' not found
toolsets = vs2008 vs2010 vs2012 vs2013;
^
error: file 'C:\winsparkle\WinSparkle.bkl' is invalid
Any suggestions on what might be going wrong ??
If you want to regenerate the projects for some reason, you'll need Bakefile 1.x, not 0.2.x: https://github.com/vslavik/bakefile. Or just use the projects included in the repository.
Thrift File:
struct Sub {
1: required i32 number
}
struct Message {
1: required Sub sub
}
Message m;
m.write(protocol.get());
Message parsedM;
parsedM.read(protocol2.get());
std::cout << parsedM.sub.number;
SourceCode
Should not Thrift raise an error or is there any other possibiliy to properly check if all required field have been set?
Otherwise I see no real point in that keyword.
Short answer
Yes, you should get a TProtocolException::INVALID_DATA if the data are not present while deserializing. That's not the case in your example, so you don't get the exception.
Long answer
This is one of the generated C++ read() methods based on your IDL. Watch out for isset_number and how it is used:
uint32_t Sub::read(::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using ::apache::thrift::protocol::TProtocolException;
bool isset_number = false;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == ::apache::thrift::protocol::T_I32) {
xfer += iprot->readI32(this->number);
isset_number = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
if (!isset_number)
throw TProtocolException(TProtocolException::INVALID_DATA);
return xfer;
}
So why does it work in your example?
As we have seen, required fields are expected to be present in the deserialized data, while optional (and default) fields may be missing. But fields marked required (and default fields) are also always written to the transport, optional only when a value has been assigned. Hence you read the data that you serialized before:
uint32_t Sub::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("Sub");
xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I32, 1);
xfer += oprot->writeI32(this->number);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
Note that Thrift does not care about whether the field contains valid data. It's all about the serializing aspect.
Recommended reading
Diwaker Gupta's "Missing Guide" explains the pros ands cons of required quite good.