Closed chenqingguo closed 4 years ago
What command did you run?
I can build with the following command on x64 Native Tools Command Prompt for VS 2019:
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -A x64 -DPostgreSQL_LIBRARY="<PATH_TO_POSTGRES>/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="<PATH_TO_POSTGRES>\include" -DPostgreSQL_TYPE_INCLUDE_DIR="<PATH_TO_POSTGRES>\include"
cmake --build . --config Debug --target -j 8
NOTE -A
option is important. When this option is not specified, even if you execute CMake on 64bit OS, the generated project file is for 32bit OS.
Visual Studio 15 2017 — CMake 3.17.1 Documentation:
For each toolset that comes with this version of Visual Studio, there are variants that are themselves compiled for 32-bit (x86) and 64-bit (x64) hosts (independent of the architecture they target). By default this generator uses the 32-bit variant even on a 64-bit host. One may explicitly request use of either the 32-bit or 64-bit host tools by adding either host=x86 or host=x64 to the toolset specification. See the CMAKE_GENERATOR_TOOLSET variable for details.
Well. Here is my command
mkdir build cd build cmake .. cmake—build. —target INSTALL
it works after add -A x64
.
Do I need to copy the include and lib to my program? I thought make install
and add find_package
in my cmakelists is all what should do.
Thanks
Do I need to copy the include and lib to my program?
No, specify lib and include only if CMake cannot find the PostgreSQL library. I have specified it because my machine has a custom install of libpq.
I also had (and fixed) issues with Visual Studio 2019 (version 16). (And thanks for some of the comments on istall, I will integrate those into my process.)
I had bugs appear. I just installed the new version of VS 2019 in last few days, so I suppose the latest. Compiling for 64 bit (-A flag) and 2019, etc., and test in debug mode. Neither the test suite, nor the actual library, would run correctly until I made 2 modifications:
Here is what I did to fix:
IN strconv.cxx, starting line 478:
case 'N':
case 'n':
// Accept "NaN," "nan," etc.
ok = // [GLE] Note text[3] does not exist and triggers failure.
(text.length() == 3 and (text[1] == 'A' or text[1] == 'a') and
(text[2] == 'N' or text[2] == 'n') /*and (text[3] == '\0')*/);
IN test_main.hxx, starting line 134. Note that test_main.hxx does not appear in the project directory, is one directory level above runner.cxx in either of the 'runner' or 'unit_runner' sub-projects. It is included in the respective runner.cxx file, and I followed the link. This is a common file, and only needs to be changed once for both sub-projects:
// [GLE] add argc and make test_name null without an an argv[1].
int main(int argc, char const *argv[])
{
char const *const test_name = argc>1? argv[1]: NULL;
THESE ARE THE ONLY MODIFICATIONS that I needed to successfully run the entire testing suite for pqxx with Visual Studio 2019.
For the record, @GordonLElliott filed these problems as #307, and the fixes have been merged into master
and the 7.1 working branch (see #274).
@chenqingguo is your problem solved now?
I have just released 7.0.6, which contains the fixes mentioned here.
<...>
I can build with the following command on x64 Native Tools Command Prompt for VS 2019:
mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -A x64 -DPostgreSQL_LIBRARY="<PATH_TO_POSTGRES>/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="<PATH_TO_POSTGRES>\include" -DPostgreSQL_TYPE_INCLUDE_DIR="<PATH_TO_POSTGRES>\include" cmake --build . --config Debug --target -j 8
For my purposes, I coplied the cmake commands into a batch file (which also set up the MS variables). This was very helpful--I was completely new to Cmake. (Started with an old version installed and 3 versions of PostgreSQL including an X86, so Cmake found every possible way to mess up that it could find. The above would force correct versions of everything, I think, or at least fail so I knew what to fix. Especially thanks for this and all the othr work--and consider more detail in the notes on build for Microsoft. (Especially that second line using cmake --build. The original notes suggested some sort of 'make' which doesn't even exist on today's Microsoft. My version found a 16 bit copy somehow!!!)
OH--then after that of course cmake supplies a native Visual Studio 2019 solution file. The user can also directly open that and configure for debug and release there. I personally configured for Unicode characer set, which worked fine--I didn't find yet how to integrate that request into the cmake build. User's may not realize that the solution file is built.
I will comment that finding the final library in a subdirectory of 'src' is weird (that is where it goes on my build). I would prefer it went in a 'lib' directory at same level not inside of 'src'.
I will comment that finding the final library in a subdirectory of 'src' is weird (that is where it goes on my build). I would prefer it went in a 'lib' directory at same level not inside of 'src'.
@GordonLElliott In the src
directory are build artifacts.
Just as Visual Studio outputs default artifacts to bin\Debug
, placing build artifacts in the lib directory is considered another task.
For CMake, moving from the src
directory to the lib
directory is done when you run the install target generated by CMake: https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project
Thanks both, I think I have some work to do on the build docs. I'm still not particularly familiar with CMake myself, so I just learned a few things I didn't know!
I have built pqxx for 64 win. Now when I include it to the project, I have this error:
pqxx.lib(connection.cxx.obj) : error LNK2019: unresolved external symbol __imp_WSAPoll referenced in function "void __cdecl `anonymous namespace'::wait_fd(int,bool,struct timeval *)" (?wait_fd@?A0x909bfe52@@YAXH_NPEAUtimeval@@@Z) project6_part2.exe : fatal error LNK1120: 1 unresolved externals
Sounds like you need to link to the socket library... Is it called ws2_32
on Windows? It may take more.
In the configure
build, I link with ws2_32
, wsock32
, and/or winsock
, as available, in that order. The CMake build links only to those first two — I think the last one may be an older thing. So perhaps your application needs to link with ws2_32
and wsock32
as well.
wsock32
it helped. Thank you. But now I've got abort message. My code:
#include <iostream>
#include <pqxx/pqxx>
int main() {
pqxx::connection C;
return 0;
}
@joeyave Maybe throw exception from pqxx::connection
constructor.
You should add try-catch statement.
@jtv yes, buildiing succeed, but I think make install
in windows is invalid.
I'm learning how to use pqxx, I want to insert 'std::vector<real[]
of pg database.
Here is my test code,
******
pqxx::stream_to inserter(transaction,"test");
for(int i=1; i<99;i++)
{
tmpData tmpdata;
tmpdata.id=to_string(i);
tmpdata.feature=vector<float>(0.1*i,500);
inserter<<std::make_tuple(tmpdata.id,tmpdata.feature);
}
inserter.complete();
transaction.commit();
the result of id in database is right, but the array is incorret. The array is {}
in my table--test.
Is there an approprite way to insert vector using pqxx?
@chenqingguo
make install
in windows is invalid.
Since CMake 3.15, use cmake --install <dir>
instead: https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project
Another way is to use cmake --build . --target install
: https://stackoverflow.com/questions/34040522/is-there-a-cmake-install-switch/34040747
Good point. When you construct a connection
, you connect to the database. That could be failing because the database is not running, or because it's on a different port, or because your default user does not exist, or you need to provide a password, or because the database does not exist...
Catch the exception and print its what()
message.
OH--H****. Fail is I'm running install without admin privilages--will try that next!!!!!!!!!!!!!!!!!!!!!!!!!
The cmake --install appears to fail, and also triggering the "INSTALL" in the VS 2019 IDE also fails. Just references the post build batch as whole, and error 1, no detailed explanation.
FOR ALL SHOWING a method to do install -- please tell if you have actually tested this method successfully! (As opposed to just finding cmake instruction; which is tremendously valuable of course because it is the only way we will figure it out.)
I saw install location variables somewhere in the original materials. I syspect that something is wrong in all that setup so that the GUI based install does not work out.
By the way, the "PACKAGE" utility in the GUI successfully creates a gzip file--I have no idea yet what it does.
HEY! The "PACKAGE" builds a gzip of a the install needed. But this step executes in my VS gui, while the "INSTALL" step fails. I can extract the gzip that it creates as a binary install....... I will try that and report. At least this shows that the essence of "INSTALL" is already working, just some specific failure in the project as automatically constructed.
This gzip contains the pqxx library, and clean copies of the include directory!
NOTE: See messages below--successfully installed (need to be administrator), but it put in the Program files (X86) directory. Otherwise very nice. -- IN CASE these notes were useful....
I am still trying to do an "install" (don't know how yet) on X64 build, so the copies needed for regular usage are in the weird locations (as mentioned above).
But the build package also includes examples in the form of the tests (runner, unit_runner) which demonstrate linking for X64 in the weird locations of the build. Can use that until get an install to a sensible location for all.
Specifically for person with linking in x64, here are my libraries (obviously change to correct locations on your system):
In properties--linker--additional dependencies:
C:\pqxx_7\build64\src\Debug\pqxx.lib;C:\Program Files\PostgreSQL\12\lib\libpq.lib;wsock32.lib; .....
where ..... is the original on that line. Obviously I built at top level C drive in my case so I could use for the time being, you can figure out what I did. (Someone comment on missing socket library???) This compiles. I have not tested yet my dummy application which does not have connect string so I will need to set up environment variables, which can be done in the VS debugger by the way for testing.
THERE SHOULD be better practice than this method, for example set library path separately and only library names in the list of libraries. (That way only fix the paths when change compiler setup, but it is the sema library wherever it lands.) This example is just to get the list which then does work.
(Also here is what I set to refer to the not-yet-installed library include files, once again copying from the test cases): IN properties--C/C++--general--Additional Include Directories (here the full line)
C:\Program Files\PostgreSQL\12\include;C:\Program Files\PostgreSQL\12\include\server;C:\pqxx_7\build64\include;C:\pqxx_7\libpqxx-master\include;%(AdditionalIncludeDirectories)
And I need to configure my build for Unicode, not multi-byte character set. (Did I already mention?)
I have successfully done that manually. First cmake to build the VS solution. Then open with VS and change the pqxx, runner, and unit_runner properties to use Unicode. This works successfully and the test suite works completely. However it is a manual intervention and as yet not "installed" (since I don't know yet how to do that and the install job in the VS solution fails). All references I have found on the Internet suggest this must be burried in the cmake setup files, and if done then possibly give a define option to trigger automatically. For now even if I had an install step that worked, I would have to stop for the manual intervention to set Unicode character set, so I could not automate as a continuous build--install process with a single batch file either.
Everyone ignore my statement that INSTALL project does not work.
It works (sort of) if you run with administrative permissions. Either in a batch file (I presume) with admin privilages, or in separate step. I will describe how to run INSTALL from VS2019 IDE (presumably works others).
The trick is that even if you are logged in as admin, the VS2019 IDE does not run as administrator. That makes sense, you don't want compiling events (which may have been written by others) to trigger operating system changes--that could introduce viruses etc when unscrupulous persons are involved.
So after build steps have worked (and in my case use the VS IDE to change to Unicode character set and rebuild, or any other changes you require). THEN exit the VS IDE (if open).
Then go to the start menu and find your VS IDE, and right click and follow more options to "run as administrator".
DO NOT do any other tasks as admin -- I recommend -- just the install.
Right click on the INSTALL project, and build.
Even though I built as X64, it installed the library and include files in the C:\Program Files (x86)\libpqxx directory for Win32 programs.
OTHER than that--this is a very nice install, clean of almost everything supurflous.
The methods using a command line (say in batch file) to trigger this may have options to override. Or one could take the post build event, make a batch file, and edit to include additional directive to select the correct location--I have not figured that out yet.
ALSO note that the PACKAGE project builds a gzip of the same files. Then you could manually or by batch file (as administrator) expand the gzip into the correct location, either program files (and not the (x86) directory) or if you chose a different install location. Once again someone may figur out how to set this into the INSTALL project--probably a -D or something.
I will be testing usage of this and report....
@GordonLElliott You can change install location with --prefix
option. e.g: cmake --install <dir>--prefix <install-prefix>
See cmake --install
document: https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project
Another way: cmake -DCMAKE_INSTALL_PREFIX=<instal-prefix>
https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html#variable:CMAKE_INSTALL_PREFIX
CMake is a cross-platform tool. It is the user's responsibility to perform the installation with administrator privileges, when writing during installation requires administrator privileges. Due to security issues, CMake functionality cannot ignore permissions. This is also true for Linux and MacOS.
I just downloaded the latest, applied my (slightly updated) batch file, and used the INSTALL project (as described above using administrator priviledges). Then tested the library with a modified Employee database example program.
Another way:
cmake -DCMAKE_INSTALL_PREFIX=<instal-prefix>
I added to my original build batch file the suggested install prefix (thanks tt4g) which worked perfectly. I used that method rather than a cmake --install method since I wanted the built up project (VS 2019 solution) to have the target within itself, so that could be run from the IDE. This worked perfectly, and the INSTALL project installed in the desired directory.
Furthermore I tested with both null and empty string ('') data in database for conversion to both int and float types, and found that the throw reports were completely consistent and no debugging traps occured. So all the new changes work.
Here is my batch file to build (but not install) the project from just raw data:
rem GLE build pqxx7...
rem
rem ** First delete all subdirectories (namely build and any old libpqxx-master)
rem Copy new clean copy of libpqxx-master directory in to this directory. Cmake line
rem must properly refer to this location (Files should be just under libpqxx-master) **
rem
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
md build64
cd build64
cmake ../libpqxx-master -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -A x64 -DPostgreSQL_LIBRARY="C:\Program Files\PostgreSQL\12/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DPostgreSQL_TYPE_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DCMAKE_INSTALL_PREFIX="C:\pqxx_7.0.6_new"
if %errorlevel% neq 0 goto :error
cmake --build . --config Debug --target -j 8
if %errorlevel% neq 0 goto :error
goto :OK
:error
echo Failed with error #%errorlevel%.
pause
exit /b %errorlevel%
:OK
pause
I'm sure there are better ways to do this, but it demonstrates all the features. Of course change all directories to be correct for your machine. I just click on the batch file in a directory with only the batch file and latest libpqxx-master directory, and it builds the Solution for Visual Studio 2019. Then building the INSTALL project (with IDE opened as administrator) installs correctly.
Thanks again to everyone who contributed ideas, too numerous to name. I started with a cmake that referred to the wrong version of PostgreSQL, built the wrong kind of program using the wrong version of Visual Studio and put it in the wrong place. (And crashed in the debugger without running the verification testing.) Now (with extra thanks to jtv) I have a clean install that passes all test!
Thanks for figuring this all out and documenting it!
I simplified the batch file, removing some flags that were not in the documentation or help, or otherwise the system complained about and didn't work.
rem Build pqxx from CMake files. (Place libpqxx-master directory with files in parallel with batch file)
rem Output will be placed in directory build64. Run Visual Studio as Administrator to build INSTALL as Release.
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
if %errorlevel% neq 0 goto :error
cmake -S libpqxx-master -B build64 -G "Visual Studio 16 2019" -A x64 -DPostgreSQL_LIBRARY="C:\Program Files\PostgreSQL\12/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DPostgreSQL_TYPE_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DCMAKE_INSTALL_PREFIX="C:\Program Files\libpqxx"
if %errorlevel% neq 0 goto :error
rem change Release to Debug to pre-build a debug copy. IDE opens as Debug no matter what.
cmake --build build64 --config Release
if %errorlevel% neq 0 goto :error
pause
goto :EOF
:error
echo Failed with error #%errorlevel%.
pause
exit /b %errorlevel%
This will build a Release -- or change the one occurrence of "Release" to "Debug" will build a debug copy. Note that the libpqxx.sln solution will be set for "Debug" no matter what (we have not found a switch that changed the setting on the solution, the build config only afects which was pre-compiled in the batch file not the solution itself.
Then as before use the IDE run as Administrator to actually install, or possibly set up a batch file to trigger the INSTALL project in the solution. The INSTALL project will be configured to install in the C:\Program Files\libpqxx directory.
Now the problem: The install for Debug and Release put the pqxx.lib file in the same location. Yes, I could make completely different projects for Debug and for Release, with complete duplicate copies of the include files and documentation.
Furthermore the install does not copy the pqxx.pdb file along with the pqxx.lib in the Debug install. So if you were to recompile the Debug pqxx project without installing, then you can't link to the debug .lib file any more because it actually referes back to the .pdb file in your compile directory. (I tested this and it failed--but if I install the .pdb with the .lib then it does not fail just by rebuilding the pqxx project.)
By the way, the source files become an important part of the debug installation, where they were compiled. If you step into a user program compiled against the debug pqxx.lib you can step into the source debugging with the files in their location where they were compiled.
https://www.wintellect.com/pdb-files-what-every-developer-must-know/
Method I would recommend is either maintain separate locations for release and debug install, or my manual method: I copy the generated pqxx.lib and pqxx.pdb into a lib\Debug directory alongside of the release lib\pqxx.lib file. (Could make a batch file for that install approach I suppose--still a missing aspect of the install methodology.) The install method has already done the heavy lifting of separating out the include, document, and possibly release library, so this is a minor step.
@GordonLElliott I think only some developers install debug-built libraries.
They can freely change the installation location with CMAKE_INSTALL_PREFIX
.
@GordonLElliott I think only some developers install debug-built libraries. They can freely change the installation location with
CMAKE_INSTALL_PREFIX
.
As I mentioned, that results in duplicate include and document directories as well, and does not resolve the lack of the pqxx.pdb in the install directory.
The IDE build produces a nice directory (though weird location) build64\src\Debug . I suppose I could make a batch file to copy the Debug directory to the install lib diretory, after building both Debug and Release configurations and installing the Relase first to set up the entire structure and heavly lifting.
The IDE build produces a nice directory (though weird location) build64\src\Debug . I suppose I could make a batch file to copy the Debug directory to the install lib diretory, after building both Debug and Release configurations and installing the Relase first to set up the entire structure and heavly lifting.
The build directories are separated because you are using Visual Studio as a generator with CMake.
MinGW and gcc should not create Debug
or Release
directories.
As a result, batch files will not work cross-platform.
CMake scripts are currently maintained by contributors.
After adding the batch file, someone must maintain it.
Furthermore, CMake also has RelWithDebInfo
and MinSizeRel
as build type.
Don't forget these things for full support.
I can't decide whether or not to support it, as all support adds work to the project.
That .pdb problem is important, if we have a separate install method (separate from the build, I mean). And the separate install method is important to separate out the proper include files from the larger source code project.
I'm not sure why so many build types are needed (just because CMake supports them). I definitely do in some cases of embedded systems I work on, I really needed a debug of release compiled code because it wouldn't fit in a tiny chip. But on these kind of projects, why more than debug and release? Even typical Microsoft IDE created projects only default with those two options. Oh, yes I have had failures that only occurred in relase compile and wanted to debug..... (but rare). (These kinds of failures were actually the kind that the modern complier caught in the original code here before the last few fixes, like referencing non-existent memory locations that changed between debug and release. Now debug versions trap these more often.)
If we can only have a way to distinguish the library locations for Release and Debug, and include the pqxx.pdb file in Debug, that is all the distinguishing I think is needed. Already more than I expected.
I only meant the batch files as examples--one would never release them, just possibly in documentation as examples specific to Windows. Users would need to configure the options themselves anyway and they are mostly just setting parameters one would have a pain doing for CMake if not in a script of some sort. And I am desperate to get this to work, have multiple projects to convert to pqxx 7.
By the way, I understand some only use release, but then why are they compiling in the first place? If they are doing more than recompiling someone else's project for release, then they are debugging!
If we can only have a way to distinguish the library locations for Release and Debug, and include the pqxx.pdb file in Debug, that is all the distinguishing I think is needed. Already more than I expected.
Specify the absolute path to the location of the .pdb
file in the generated .lib
.
Therefore, it does not make sense to modify the .pdb
file generated during installation.
Because .lib
and .dll
cannot find the relocated .pdb
.
If you absolutely want to place .pdb
in the installation destination, specify CMake variable PDB_OUTPUT_DIRECTORY
as the installation destination:
PDB_OUTPUT_DIRECTORY — CMake 3.17.1 Documentation
Since the .pdb
file is created at the destination specified in this variable, the path of the .pdb
file in .lib
will also be the specified path.
CMake installs include files and release libraries needed by many users by default. Due to the large size of pdb files and debug libraries, many users do not need to install them. I think it makes sense to customize the installation of it with CMake arguments.
@jtv
Catch the exception and print its what() message.
I do have catch, It's just a part of code not all. Connection and database are ok, and inserting string
is ok but not vector
.
I found a array test, and solve my problem.
Ah..., investigating. But:
https://cmake.org/cmake/help/latest/prop_tgt/PDB_OUTPUT_DIRECTORY.html
But in the documentation on that page:
Note This property does not apply to STATIC library targets because no linker is invoked to produce them so they have no linker-generated .pdb file containing debug symbols.
This is flat out wrong! There is a pqxx.pdb alongside the pqxx.lib in the
I'll investigate if there is also a way to specify the .lib location, and use only for the debug build. Actually try the PDB_OUTPUT_DIRECTORY first and see what it does.
PS I don't understand "Therefore, it does not make sense to modify the .pdb file generated during installation." I just want that .pdb file placed along side the .lib in the install directory (distinct of course from the Release pqxx.lib). The present Debug INSTALL does not put a copy of the pqxx.pdb in the install directory at all!
OK--I take back some comments, I'm not sure that PDB_OUTPUT_DIRECTORY is relevant. Of course the notion of where it puts the ".pdb" is what I am after--but where it puts the .pdb on the INSTALL step, not the build step. Since the PDB_OUTPUT_DIRECTORY flag is changing the input to the linker, the documentation may be right in the sense that placing that flag value in a linker is not useful and will not work here.
HAVE TRIED many variations, nothing works so far...
I don't understand the src/CMakeLists.txt . I even regenerated it from the template and it still works, but:
The only location I see installing files is in the macro, that having a condition:
if(NOT name STREQUAL output_name AND NOT CMAKE_HOST_WIN32)
If it only installs files when NOT on Windows, where are the rules to set up the install project?
I've run out of time to try to figure out internal options. The command line options in this batch file have pretty much been tested to all work and are documented. (Other ideas have not worked so far.)
This batch file uses the CMake built INSTALL program of Visual Studio solution to install both the Release and Debug projects.
It uses normal install process for Release, then circumvents the CMake process to copy the Debug result into the target directory, in the lib/Debug subdirectory -- complete with both pqxx.lib and pqxx.pdb. You have to maintain the original compile directory to enable debugging into pqxx functions--which works in my case. (There are many tutorials on placing source code and Microsoft .pdb files for enterprese level debugging--this is just simple set up a project source directory of your own here and place the batch file and source files directory there..)
Updated so you can set MultiByte (default) or Unicode character set. (I need Unicode, while build defaults to MultiByte in the IDE.)
Batch build file:
REM Build pqxx from CMake files. (Place libpqxx-master directory with files in
REM parallel with batch file.) Intermediate files will be placed in directory
REM build64. Installs both Release and Debug to INSTALL_DIRECTORY location.
REM Requires administrator privileges if INSTALL_DIRECTORY is Program Files.
REM *** Builds both Release and Debug. Installs Release using INSTALL in IDE
REM *** from CMake. THEN circumvents Cmake process by copying the Debug output
REM *** to the install target lib directory, lib\Debug, with the pqxx.pdb file.
REM ***
REM *** *** SET YOUR INSTALL DIRECTORY Here ***
setlocal
SET INSTALL_DIRECTORY="C:\pqxx_7.0.6"
REM Set cores to number of CPU cores on your machine, or 1 to disable. Set 8
REM cores only shaves 1.5 minutes out of 9-10 minute compile time on an older
REM computer, probably because multi-tasking gets confused and compiles some
REM files multiple times with more than one cores.
SET CORES=1
REM CHARSET must be exactly "Unicode" or "MultiByte" or else will not work
REM correctly:
REM SET CHARSET="Unicode"
SET CHARSET="MultiByte"
REM Note that the VS IDE solution is set for MultiByte, regardless of this
REM setting. If you use Unicode and intend to comple in the IDE, you must
REM change pqxx, runner, and unit_runner projects to Unicode character set.
echo Start %CHARSET% build, cores: %CORES% >> timer.txt
echo Start build: %time% >> timer.txt
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
if %errorlevel% neq 0 goto :error
cmake --verbose -S libpqxx-master -B build64 -G "Visual Studio 16 2019" -A x64 -DPostgreSQL_LIBRARY="C:\Program Files\PostgreSQL\12/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DPostgreSQL_TYPE_INCLUDE_DIR="C:\Program Files\PostgreSQL\12\include" -DCMAKE_INSTALL_PREFIX="%INSTALL_DIRECTORY%"
if %errorlevel% neq 0 goto :error
REM change Release to Debug to pre-build a debug copy. IDE opens as Debug no
REM matter what.
REM Usage: cmake --build <dir> [options] [-- [native-options]]
REM Options:
REM <dir> = Project binary directory to be built.
REM --parallel [<jobs>], -j [<jobs>]
REM = Build in parallel using the given number of jobs.
REM If <jobs> is omitted the native build tool's
REM default number is used.
REM The CMAKE_BUILD_PARALLEL_LEVEL environment variable
REM specifies a default parallel level when this option
REM is not given.
REM --target <tgt>..., -t <tgt>...
REM = Build <tgt> instead of default targets.
REM --config <cfg> = For multi-configuration tools, choose <cfg>.
REM --clean-first = Build target 'clean' first, then build.
REM (To clean only, use --target 'clean'.)
REM --verbose, -v = Enable verbose output - if supported - including
REM the build commands to be executed.
REM -- = Pass remaining options to the native tool.
REM (On pass options):
REM https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019
REM NOTE that -j parametr more than 1 allows for faster compiling, but
REM may re-compile a file more than once. Set no higher than number of
REM cores on your computer.
REM Note that addition of -- /p:CharacterSet=Unicode
REM does change from _MBCS to UNICODE, which can be observed in the
REM CL command line used (as shown by --verbose) in compile,
REM but does not change the MS solution file in the IDE.
cmake --build build64 --verbose --clean-first --config Debug -j %CORES% -- /property:CharacterSet=%CHARSET%
if %errorlevel% neq 0 goto :error
cmake --build build64 --verbose --clean-first --config Release -j %CORES% -- /property:CharacterSet=%CHARSET%
if %errorlevel% neq 0 goto :error
REM ********************************************************************
REM **** Below this point, requires administrator privileges, ****
REM **** if that is required by the INSTALL_DIRECTORY. If so, ****
REM **** recommend breaking into separate batch files so that ****
REM **** build is not done with administrator privileges. ****
REM ********************************************************************
REM Install the Release copy in the normal manner. This does the
REM heavy lifting of include and doc directories as well as lib with
REM Release library, also in the normal manner.
cmake --build build64 --target INSTALL --config Release
if %errorlevel% neq 0 goto :error
REM Here copy the Debug directory (Return 0 up to date, 1 copied OK)
robocopy "build64\src\Debug" "%INSTALL_DIRECTORY%\lib\Debug" /MIR /E /R:0 /DCOPY:T /Z
if %errorlevel% gtr 1 goto :error
REM ********************************************************************
REM **** Error and exit processing ****
REM ********************************************************************
REM You can double click this file in the top level directory for the project,
REM and pauses so the command window does not go away before you see the
REM results. The timer.txt file shows start and end times of the batch runs.
echo End build: %time% ***>> timer.txt
pause
goto :EOF
:error
echo Failed with error #%errorlevel%.
pause
exit /b %errorlevel%
This has been tested wtih a modified Employee example program set to the library and include as installed, compiled in both Debug and Release configurations. As before seems to pass all tests, and debugging can step right into the pqxx library source in your original build location.
Copying (or not copying) the pqxx.pdb file is a complex subject, as is where to keep the original source which must be maintained if one is to debug into that source. See:
https://www.wintellect.com/pdb-files-what-every-developer-must-know/
Other options with an easy change of the batch file would be to copy only the library to Debug subdirectory, or copy the library with a 'd' suffix, etc. (If Cmake were easier to navigate and had better support for Microsoft these cases would all be easy to make as command line options--they are all common methods used in the Microsoft world. I understand that Cmake is supporting an amazing array of target systems--this above is a quick and dirty method to get me going!)
PS I don't understand "Therefore, it does not make sense to modify the .pdb file generated during installation.
The debugger looks for and loads .pbd
from the same path where the .pdb
file was generated and the same directory as the .exe
when loading the .pdb
.
This means that once a generated .pdb
file is installed in the same directory as.lib
, it doesn't make sense to most users as it won't load during debugging.
debugging - C++ PDB Symbols not loaded from same directory - Stack Overflow
These settings assume the directory I used in the previous post, of pqxx.7.0.6, not Program Files. (You can edit to your preferences of course). I did that to keep my build simple without admin priviledges, but of course you will want to set your own policies.
Set for all configurations.
Properties--Configuration Properties--VC++ Directories--Library Directories:
C:\pqxx_7.0.6\lib;C:\Program Files\PostgreSQL\12\lib\;$(VC_LibraryPath_x64); ....
The .... is whatever your project default generated.
Then ... C/C++--General--Additional Include Directories:
C:\pqxx_7.0.6\include;C:\Program Files\PostgreSQL\12\include;C:\Program Files\PostgreSQL\12\include\server
(Apparently was blank as default??)
I am not sure this is best practice... May want to put these in Properties--Configuration Properties--VC++ Directories--Include Directories, so as to be consistent with the other directory changes. (PS: Tested with prepending to VC++ Directories--Include Directories and worked fine, I think this is more consistent. I don't know the distinction.)
Then ...C/C++--Language--C++ Language Standard:
ISO C++17 Standard (/std:c++17)
Then Release: ...--Linker--Input--Additional Dependencies:
pqxx.lib;libpq.lib;wsock32.lib;ws2_32.lib; ...
(I'm pretty sure this agrees with the dcumentation to this point.) ... is default from new project. I did the configuration specific because often the library names are different on debug and release.
Then same for the Debug configuraion:
Debug\pqxx.lib;libpq.lib;wsock32.lib;ws2_32.lib; ....
Thus differentiating the debug library (in this case into a subdirectory--other libraries might use a 'd' suffix for debugging, etc, in this field.
Unless I am mistaken, that is all the modifications from default new VS2019 project setup as Console app that I needed.
The debugger looks for and loads
.pbd
from the same path where the.pdb
file was generated and the same directory as the.exe
when loading the.pdb
. This means that once a generated.pdb
file is installed in the same directory as.lib
, it doesn't make sense to most users as it won't load during debugging.
See a previous post I made. I am sure there are different ways to do this. In your linked website, they said they "moved" the PDB, and I don't know if they really meant "move" or just "copy". Moving would be a weird thing to do, IMO.
https://www.wintellect.com/pdb-files-what-every-developer-must-know/
As per my referenced pages (duplicated here), I tested with and without COPY of the pqxx.pdb to be next to the pqxx.lib in the local install directory. In both case, I could compile and then debug right into the source code in the original compile location.
NOW the difference:
Without the copy of the pqxx.pdb, if I simply rebuilt the source library -- not re-installing the pqxx.lib in the install directory, just recompile the source---:
Then I can no longer link the debug without errors! (Same if the source became temporarily unavailable as on a network drive.)
(I thik there are serious probelms if you change the source and do not install, however, since the line numbers in the PDB file would no longer agree and debugging into pqxx source would get weird!)
But another case is where the source is kept on a removable or network drive. Then one can go off and compile without connection to the network drive (if .pdb file is local) and debugging will only fail when one actually steps to one of the files that are offline.
Without the .pdb in the install--the linker requires the .pdb to be available at the source location at the time of the linking.
Note the 2nd' search location is besid the library (or DLL or EXE) file, the first search is the original. That is why compiling still works with the local copy, but it is not used if the original source is present. THIS IS a complicated subject--and I am sure that there are many cases where one does not want the PDB file to be copied. I do still want a separate copy of the debug library, and prefer not to have a complete separate install of the include and doc to go with that.
What I keep wondering about is: how do people normally do all this with CMake and Visual Studio!?
@jtv IMO.
Visual Studio IDE should be able to build libpqxx with CMake.
@chenqingguo who opened this issue seems to be unable to resolve the issue in this comment (https://github.com/jtv/libpqxx/issues/306#issuecomment-619465928).
There is a comment that mentions installing the debug symbol file (.pdb
) with CMake,
As I commented above (https://github.com/jtv/libpqxx/issues/306#issuecomment-619464356), most users don't need it, so I don't think I need support.
I think chenqingguo figured out his problem, because I learned to do what I did in part from one of his posts.
One thing I realized is that we don't have to find the compiler location--CMake does that! (Especially if you specify the compiler).
Here is much simpler batch file that uses VS 2017 (and tested that it makes a library without complaint):
REM Cmake build of libpqxx for Visual Studio 2017.
REM *** *** SET YOUR INSTALL DIRECTORY Here ***
setlocal
SET INSTALL_DIRECTORY="C:\pqxx_7.0.6_VS2017-x64"
REM Remove the Win64 if you want a 32 bit compile: "Visual Studio 15 2017"
cmake --verbose -S libpqxx-master -B buildVS2017-x64 -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX="%INSTALL_DIRECTORY%"
if %errorlevel% neq 0 goto :error
REM change Debug to Release if you don't want a debug library.
cmake --build buildVS2017-x64 --target INSTALL --verbose --config Debug
if %errorlevel% neq 0 goto :error
pause
goto :EOF
:error
echo Failed with error #%errorlevel%.
pause
exit /b %errorlevel%
Comments show how to switch to 32 bit or to Release configuration.
One can put this into a batch file alongside of directory libpqxx-master with all the files just underneath that, and double click the batch file to run it. This creates the working and install directories. (No changing directory.)
@GordonLElliott See this comment and CMake document
-G "Visual Studio 15 2017 Win64"
is old CMake generater name.
The recommended platform option is -A
since CMake 3.2 and above.
well, I don't think providing a batch file is a good way. Chossing which platform,directory or something else to compile should be done(accroding to user's compiler) in cmaklists. Centos is my product environment, and I focus on how to use API efficiently.
I agree (and I think that everyone here probably agrees) that it'd be best to have a CMakeLists that "just works."
Question is, how do we get there?
@jtv CMake is similar to the autotools configure script. It is recommended to specify the compiler etc to be used by the argument when executing CMake
The big difference from the configure script is that it generates a build tree other than Makefile according to the CMake generator.
Generates a Makefile or project file that a CMake generator, such as make, Ninja, or Visual Studio, specified by the -G
option can perform the build (this feature makes CMake a cross-platform tool).
Unfortunately, as far as I know, the CMake generator cannot changed when CMake is executed and should not be changed in CMakeLists.txt
.
the only solution to the first issue mentioned in this issue is for the user to specify a CMake generator with the -G
option: https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html
See also: What is a CMake generator? - Stack Overflow
In other words, CMakeLists.txt
should work, but it didn't work because the options CMake needed were not passed.
Addition:
the user can change the compiler and compile options, etc. We should check the CMake documentation for how to set up the build tool. I think here is how to change the typical toolset.
For example, the default C++ compiler determines from the CXX
environment variable: CXX — CMake 3.17.1 Documentation
Specify CMAKE_CXX_COMPILER
variable to use a compiler different from CXX
environemnt variable (e.g. cmake -DCMAKE_CXX_COMPILER=clang
).
I've been giving batch file lists for a number of reasons. For one they document commands that could be entered by hand--but are a lot of trouble to type out. Also I needed something to use to get the job done the way I wanted for my clients, and the CMake by itself did not work.
I just installed the PostgreSQL version 10 libraries. Now without specifying, it does not use the latest (12.2), but rather chooses the 10 library for use. With all the (complicated) flags I can set. Far too much to type in every time a long command line, using a batch file to do that.
Question is, how do we get there?
For example who else is more dependent upon Find Postgres than pqxx users? (That is one thing that fails for me when I have more than one install of PostgreSQL. And it is the hardest to repair because it takes at least 3 settings, as far as I can tell. But multiple compile tools is just going to happen and people simply need to tell CMake which one of theirs they want.)
An example of improving CMake (or supporting code) is: https://github.com/pgRouting/pgrouting/issues/301#issuecomment-115701087 Someone tried to solve this problem but it doesn't work and isn't documented or else was not kept.
Someone tried to solve this problem but it doesn't work and isn't documented or else was not kept.
Users can control find_package(PostgreSQL)
result by environment variable <PackageName>_ROOT
or CMake variable <PackageName>_ROOT
.
Look CMake find_package()
document:
For example, suppose PostgreSQL is installed in C:\Program Files\PostgreSQL v12
. The directory tree has the following structure.
C:\Program Files\PostgreSQL v12
|
|- bin\pqxx.dll
|- lib\pqxx.lib
`- include
If set CMake variable PostgreSQL_ROOT
to C:\Program Files\PostgreSQL v12
then find_package(PostgreSQL)
search pqxx library and header files in C:\Program Files\PostgreSQL v12
.
This indicates that the user can specify the version of the library that CMake uses.
If CMake just doesn't find the PostgreSQL library, the user can overwrite the result variable of find_package(PostgreSQL)
.
When find_package(PostgreSQL)
is called, FIndPostgreSQL.cmake
is loaded: https://github.com/Kitware/CMake/blob/master/Modules/FindPostgreSQL.cmake
By first defining the PostgreSQL_LIBRARY
, PostgreSQL_INCLUDE_DIR
and PostgreSQL_TYPE_INCLUDE_DIR
variables defined in this module, the user can directly specify the PostgreSQL library to link with.
e.g. cmake -DPostgreSQL_LIBRARY="<PATH_TO_POSTGRES>/lib/libpq.lib" -DPostgreSQL_INCLUDE_DIR="<PATH_TO_POSTGRES>\include" -DPostgreSQL_TYPE_INCLUDE_DIR="<PATH_TO_POSTGRES>\include"
Controlling the linked libraries that CMake detects requires a lot of variable definitions, so if you're new to CMake you might find it annoying. However, allowing the library search path to be specified directly saves the user in many cases.
Because the installation destination of the library is not decided in Windows OS. Some users have the library installed on the G drive, as the Windows installer provides the option to change the installation location freely. Also, the UNIX system OS has different library installation destinations depending on the distribution. The ability to specify a path to search for the library allows users who have the library installed in a different location than many users to tell CMake that location.
find_package(PostgreSQL)
is the de facto standard way to specify the libraries to link with CMake.
However, this feature is also a drawback that it is difficult to use unless you are familiar with CMake.
I ran with -DPostgreSQL_ROOT=... but it said:
CMake Warning (dev) at cmake/config.cmake:19 (find_package):
Policy CMP0074 is not set: find_package uses <PackageName>_ROOT variables.
Run "cmake --help-policy CMP0074" for policy details. Use the cmake_policy
command to set the policy and suppress this warning.
CMake variable PostgreSQL_ROOT is set to:
C:\Program Files\PostgreSQL\12
For compatibility, CMake is ignoring the variable.
So how to set "policy CMP0074" or ??--I think this can be turned on so it obeys PostgreSQL_ROOT . That would be a lot less typing than 3 variables.
I install x64 libpq then I build libpqxx using cmake and visual studio 2017. I got this
error MSB4126 Debug |x64 is invalid
. I need to build x64 libpqxx. How to do? Thanks,chenqingguo.