Compiling C++Builder project on command line - build

Is there a way to compile a C++Builder project (a specific build configuration) from the command line?
Something like:
CommandToBuild ProjectNameToBuild BuildConfiguration ...

There are different ways for automating your builds in C++Builder (as of my experience, I'm speaking about old C++Builder versions like 5 and 6).
You can manually call compilers - bcc32.exe (also dcc32.exe, brcc32.exe and tasm32.exe if you have to compile Delphi units, resource files or assembly language lines of code in your sources) and linker - ilink32.exe.
In this case, you will need to manually provide the necessary input files, paths, and keys as arguments for each stage of compilation and linking.
All data necessary for compilation and linking is stored in project files and, hopefully there are special utilities, included in the C++Builder installation, which can automate this dirty work, provide necessary parameters to compilers and linker and run them. Their names are bpr2mak.exe and make.exe.
First you have to run bpr2mak.exe, passing your project *.bpr or *.bpk file as a parameter and then you will get a special *.mak file as output, which you can use to feed on make.exe, which finally will build your project.
Look at this simple cmd script:
#bpr2mak.exe YourProject.bpr
#ren YourProject.mak makefile
#make.exe
You can provide the real name of "YourProject.mak" as a parameter to make.exe, but the most straightforward way is to rename the *.mak file to "makefile", and then make.exe will find it.
To have different build options, you can do the following:
The first way: you can open your project in the IDE, edit options and save it with a different project name in the same folder (usually there are two project files for debug and release compile options). Then you can provide your building script with different *.bpr files. This way, it looks simple, because it doesn't involves scripting, but the user will have to manually maintain coherency of all project files if something changes (forms or units added and so on).
The second way is to make a script which edits the project file or make file. You will have to parse files, find compiler and linker related lines and put in the necessary keys. You can do it even in a cmd script, but surely a specialised scripting language like Python is preferable.

Use:
msbuild project.cbproj /p:config=[build configuration]
More specifics can be found in Building a Project Using an MSBuild Command.

A little detail not mentioned.
Suppose you have external dependencies and that the .dll file does not initially exist in your folder
You will need to include the external dependencies in the ILINK32.CFG file.
This file is usually in the folder
C:\Program Files (x86)\Borland\CBuilder6\Bin\ilink32.cfg
(consider your installation location)
In this file, place the note for your dependencies.
Example: A dependency for TeeChart, would look like this (consider the last parameter):
-L"C:\Program Files (x86)\Borland\CBuilder6\lib";"C:\Program Files (x86)\Borland\CBuilder6\lib\obj";"C:\Program Files (x86)\Borland\CBuilder6\lib\release";"C:\Program Files (x86)\Steema Software\TeeChart 805 for Builder 6\Builder6\Include\";"C:\Program Files (x86)\Steema Software\TeeChart 805 for Builder 6\Builder6\Lib\"
You will also need to include the -f command to compile.
In cmd, do:
//first generate the file.mak
1 - bpr2mak.exe MyProject.bpr
//then compile the .mak
2 - make.exe -f MyProject.mak
You can also generate a temporary mak file with another name, as the answer above says, directly with bpr2mak
bpr2mak.exe MyProject.bpr -oMyTempMak.mak

Related

Loading OCaml modules not in the current directory

I'm writing a large OCaml project. I wrote a file foo.ml, which works perfectly. In a subdirectory of foo.ml's directory, there is a file bar.ml.
bar.ml references code in foo.ml, so its opening line is:
open Foo
This gives me an error at compile time:
Unbound module Foo.
What can I do to fix this without changing the location of foo.ml?
The easy path is to use one of OCaml build system like ocamlbuild or oasis. Another option would be jbuilder but jbuilder is quite opiniated about file organization and does not allow for the kind of subdirectory structure that you are asking for.
The more explicit path comes with a warning: OCaml build process is complicated with many moving parts that can be hard to deal with.
After this customary warning, when looking for modules, OCaml compiler first looks for module in the current compilation environment, then looks for compiled interface ".cmi" files in the directories specified by the "-I" option flags (plus the current directory and the standard library directory).
Thus in order to compile your bar.ml file, you will need to add the parent directory in the list of included directories with the -I .. option.
After all this, you will discover that during the linking phase, all object files (i.e. .cmo or .cmx) need to be listed in a topological order compatible with the dependency graph of your project.
Consequently, let me repeat my advice: use a proper build system.

How do I set up this visual studio (2015) custom build step (tool?). Basically I want a pre-preprocessor step that modifies header files (c++)

I want a run a build step that looks at a .h file, adds some code based on some external params, and hands the resulting file to the preprocessor.
I see the "Custom Build Step" in the project properties. It seems to need an output file. I just want to forward the results to the preprocessor.
It seems like the custom build step wants to do a 1-time process, not per-file or by file type.
The problem is that I don't know how to send my external executable the file currently being processed (eg, "HelloWorld.cpp"). $(InputName) and %(Filename) are blank and docs say it's deprecated. How do I send the filename to my external executable?
But even if I get that working, I don't want to set this per-file. I want all header files to go through this process.
Any ideas?
I've looked at:
https://msdn.microsoft.com/en-us/library/dd293663.aspx?f=255&MSPPError=-2147217396
https://msdn.microsoft.com/en-us/library/hefydhhy(v=vs.90).aspx
https://msdn.microsoft.com/en-us/library/ff770593(v=vs.140).aspx
working on a debug, x64 config on windows.
First of all, No, you cannot modify a file and pass along the results to the next stage (that I could see). I'd need some sort of Program Transformation System.
So I need an intermediate file. That file has to be added to the project, even if it gets overwritten by your code generator. I can associate c++ header files with a custom build tool, and they will all get called one-by-one in the stage of the build specified in the Custom Build Step. The custom build tool will modify the intermediate file(s), and all is well.
The VS 2015 name for the current file being processed is %(Filename). In older versions it has been $(ProjectName) and $(InputName).

NMake Optional Dependencies

We’re currently upgrading our archaic build system from a bunch of batch scripts to a makefile system using NMake. It’s challenging as we use a custom intermediate language that ends up getting translated to C++ where some of our translators can generate 10’s of files what have a common parts in the file names. The other challenging thing is we use a bunch of CSV files to configure our interfaces and these files get passed through to our configuration tools which generate more source code files. Right now I am focusing on creating the simple rules for our configuration files but can’t seem to figure out a way associate a dependency with a rule if the dependency exists. I tried to use $(wildcard xxx.csv) but found out that this command doesn’t exist for NMake like it does for GNU Make.
So how can I create my rule so that it executes and runs my commands if I have two dependency csv files that will always exists and a third csv file that will exist only when my project calls for it?
[..] will exist only when my project calls for it?
This is a bit unclear. Assuming that there is a command that - depending on some external circumstances - might generate that third csv file, you could use a "stamp file" (I think they call it "pseudo target" in NMAKE):
stamp:
command_that_might_generate_csv3
touch stamp # updates timestamp of "stamp" (or creates it)
target: csv1 csv2 stamp
command_using_all_of csv1 csv2 csv3

Add source to an existing automake program

I would like to edit an existing software to add a new source file (Source.cpp).
But, I can't manage the compilation process (it seems to be automake and it looks very complicated).
The software (iperf 2: https://sourceforge.net/projects/iperf2/files/?source=navbar) is compiled using a classical ./configure make then make install.
If I just add the file to the corresponding source and include directory, I got this error message:
Settings.cpp:(.text+0x969) : undefined reference to ...
It looks like the makefile isn't able to produce the output file associated with my new source file (Source.cpp). So, I probably need to indicate it manually somewhere.
I searched a bit in the project files and it seemed that the file to edit was: "Makefile.am".
I added my source to the variable iperf_SOURCES in that file but it didn't workded.
Could you help me to find the file where I need to indicate my new source file (it seems a pretty standard compilation scheme but I never used automake softwares and this one seems very complicated).
Thank you in advance
This project is built with the autotools, as you already figured out.
The makefiles are built by automake. It takes its input in files that usually have a am file name extension.
The iperf program is built by the makefile generated from src/Makefile.am. This is indicated by:
bin_PROGRAMS = iperf
All (actually this is a simplification, but which holds in this case) source files of a to be built binary are in the corresponding name_SOURCES variable, thus in this case iperf_SOURCES. Just add your source file to the end of that list, like so (keeping their formatting):
iperf_SOURCES = \
Client.cpp \
# lines omitted
tcp_window_size.c \
my_new_file.c
Now, to reflect this change in any future generated src/Makefile you need to run automake. This will modify src/Makefile.in, which is a template that is used by config.sub at the end of configure to generate the actual makefile.
Running automake can happen in various ways:
If you already have makefiles that were generated after an configure these should take care of rebuilding themselves. This seems to fail sometimes though!
You could run automake (in the top level directory) by hand. I've never done this, as there is the better solution to...
Run autoreconf --install (possibly add --force to the arguments) in the top level directory. This will regenerate the entire build system, calling all needed programs such as autoheader, autoconf and of course automake. This is my favorite solution.
The later two options require calling configure again, IMO ideally doing an out of source built:
# in top level dir
mkdir build
cd build
../configure # arguments
make # should now also compile and link your new source file

How to get a python .pyd for Windows from c/c++ source code? (update: brisk now in Python in case that's what you want)

How to get from C/C++ extension source code to a pyd file for windows (or other item that I could import to Python)?
edit: The specific library that I wanted to use (BRISK) was included in OpenCV 2.4.3 so my need for this skill went away for the time being. In case you came here looking for BRISK, here is a simple BRISK in Python demo that I posted.
I have the Brisk source code (download) that I would like to build and use in my python application. I got as far as generating a brisk.pyd file... but it was 0 bytes. If there is a better / alternative way to aiming for a brisk.pyd file, then of course I am open to that as well.
edit: Please ignore all the attempts in my original question below and see my answer which was made possible by obmarg's detailed walkthrough
Where am I going wrong?
Distutils without library path: First I tried to build the source as is with distutils and the following setup.py (I have just started learning distutils so this is a shot in the dark). The structure of the BRISK source code is at the bottom of this question for reference.
from distutils.core import setup, Extension
module1 = Extension('brisk',
include_dirs = ['include', 'C:/opencv2.4/build/include', 'C:/brisk/thirdparty/agast/include'],
#libraries = ['agast_static', 'brisk_static'],
#library_dirs = ['win32/lib'],
sources = ['src/brisk.cpp'])
setup (name = 'BriskPackage',
ext_modules = [module1])
That instantly gave me the following lines and a 0 byte brisk.pyd somewhere in the build folder. So close?
running build
running build_ext
Distutils with library path: Scratch that attempt. So I added the two library lines that are commented out in the above setup.py. That seemed to go ok until I got this linking error:
creating build\lib.win32-2.7
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:win32/lib /LIB
PATH:C:\Python27_32bit\libs /LIBPATH:C:\Python27_32bit\PCbuild agast_static.lib brisk_static.lib /EXPORT:initbrisk build
\temp.win32-2.7\Release\src/brisk.obj /OUT:build\lib.win32-2.7\brisk.pyd /IMPLIB:build\temp.win32-2.7\Release\src\brisk.
lib /MANIFESTFILE:build\temp.win32-2.7\Release\src\brisk.pyd.manifest
LINK : error LNK2001: unresolved external symbol initbrisk
build\temp.win32-2.7\Release\src\brisk.lib : fatal error LNK1120: 1 unresolved externals
error: command '"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\BIN\link.exe"' failed with exit status 1120
Uncontrolled flailing: I thought maybe the libraries needed to be built, so I did a crash course (lots of crashing) with cmake + mingw - mingw + vc++ express 2010 as follows:
cmake gui: source: c:/brisk, build: c:/brisk/build
cmake gui: configure for Visual Studio 10
cmake gui: use default options and generate (CMAKE_BACKWARDS_COMPATIBILITY, CMAKE_INSTALL_PREFIX, EXECUTABLE_OUTPUT_PATH, LIBRARY_OUTPUT_PATH)
VC++ Express 10: Change to Release and build the solution generated by cmake and get about 20 pages of what look like non-critical warnings followed by all succeeded. Note - no dlls are generated by this. It does generate the following libraries of similar size to the ones included with the download:
win32/lib/Release/
agast_static.lib
brisk_static.lib
Further flailing.
Relevant BRISK source file structure for reference:
build/ (empty)
include/brisk/
brisk.h
hammingsse.hpp
src
brisk.cpp
demo.cpp
thirdparty/agast/
include/agast/
agast5_8.h ....
cvWrapper.h
src/
agast5_8.cc ...
CMakeLists.txt
win32/
bin/
brisk.mexw32
opencv_calib3d220.dll ...
lib/
agast_static.lib
brisk_static.lib
CMakeLists.txt
FindOpenCV.cmake
Makefile
Are you sure that this brisk library even exports python bindings? I can't see any reference to it in the source code - it doesn't even seem to import python header files. This would certainly explain why you've not had much success so far - you can't just compile plain C++ code and expect python to interface with it.
I think your second distutils example is closest to correct - it's obviously compiling things and getting to the linker stage, but then you encounter this error. That error just means it can't find a function named initbrisk which I'm guessing would be the top level init function for the module. Again this suggests that you're trying to compile a python module from code that isn't meant for it.
If you want to wrap the C++ code in a python wrapper yourself you could have a look at the official documentation on writing c/c++ extensions. Alternatively you could have a look into boost::python, SIP or shiboken which try to somewhat (or completely) automate the process of making python extensions from C++ code.
EDIT: Since you seem to have made a decent amount of effort to solve the problem yourself and have posted a good question, I've decided to give a more detailed response on how to go about doing this.
Quick Tutorial On Wrapping C++ Libraries Using boost::python
Personally I've only ever used boost::python for stuff like this, so I'll try and give you a good summary of how to go about doing that. I'm going to assume that you're using Visual C++ 2010. I'm also going to assume that you've got a 32bit version of python installed, as I believe the boost pro libraries only provide 32bit binaries.
Installing boost
First you'll need to grab a copy of the boost library. The easiest way to do this is to download an installer from the boost pro website. These should install all the header files and binary files that are required for using the boost c++ library on windows. Take note of where you install these files to, as you'll need them later on - it might be best to install to a path without a space in it. For easyness I'm going to assume you put these files in C:\boost but you can substitute that for the path you actually used.
Alternatively, you can follow these instructions to build boost from source. I'm not 100% sure, but it might be the case that you need to do this in order to get a version of boost::python that is compatible with the version of python you have installed.
Setting up a visual studio project
Next, you'll want to setup a visual studio project for brisk.pyd. If you open visual studio, go to New -> Project then find the option for Win32 Project. Set up your location etc. and click ok. In the wizard that appears select a DLL project type, and then tick the empty project checkbox.
Now that you've created your project, you'll need to set up the include & library paths to allow you to use python, boost::python and the brisk.lib file.
In Visual Studios solution explorer, right click on your project, and select properties from the menu that appears. This should open up the property pages for your project. Go to the Linker -> General section and look for the Additional Library Directories section. You'll need to fill this in with the paths to the .lib files for boost, python and your brisk_static.lib. Generally these can be found in lib (or libs) subdirectories of
wherever you've installed the libraries. Paths are seperated with semicolons. I've attached a screenshot of my settings below:
Next, you'll need to get visual studio to link to the .lib files. These sections can be found in the Additional Dependencies field of the Linker -> Input section of the properties. Again it's a semicolon delimited list. You should need to add in libraries for python (in my case this is python27.lib but this will vary by version) and brisk_static.lib. These do not require the full path as you added that in the previous stage. Again, here's a screenshot:
You may also need to add the boost_python library file but I think boost uses some header file magic to save you the trouble. If I'm incorrect then have a look in you boost library path for a file named similar to boost_python-vc100-mt.lib and add that in.
Finally, you'll need to setup the include paths to allow your project to include the relevant C++ header files. To get the relevant settings to appear in project properties, you'll need to add a .cpp file to your project. Right click the source files folder in your solution explorer, and then go to add new item. Select a C++ File (.cpp) and name it main.cpp (or whatever else you want).
Next, go back to your project properties and go to C/C++ -> General. Under the additional libraries directory you need to add the include paths for brisk, python and boost. Again, semicolons for seperators, and again here's a screenshot:
I suspect that you might need to update these settings to include the opencv2 & agast libraries as well but I'll leave that as a task for you to figure out - it should be much the same process.
Wrapping existing c++ classes with boost::python.
Now comes the slightly trickier bit - actually writing C++ to wrap your brisk library in boost python. You can find a tutorial for this here but i'll try and go over it a bit as well.
This will be taking place in the main.cpp file you created earlier. First, add the relevant include statements you'll need at the top of the file:
#include <brisk/brisk.h>
#include <Python.h>
#include <boost/python.hpp>
Next, you'll need to declare your python module. I'm assuming you'd want this to be called brisk, so you do something like this:
BOOST_PYTHON_MODULE(brisk)
{
}
This should tell boost::python to create a python module named brisk.
Next it's just a case of going through all the classes & structs that you want to wrap and declaring boost python classes with them. The declerations of the classes should all be contained in brisk.h. You should only wrap the public members of a class, not any protected or private members. As a quick example, I've done a couple of the structs here:
BOOST_PYTHON_MODULE(brisk)
{
using namespace boost::python;
class_< cv::BriskPatternPoint >( "BriskPatternPoint" )
.def_readwrite("x", &cv::BriskPatternPoint::x)
.def_readwrite("y", &cv::BriskPatternPoint::y)
.def_readwrite("sigma", &cv::BriskPatternPoint::sigma);
class< cv::BriskScaleSpace >( "BriskScaleSpace", init< uint8_t >() )
.def( "constructPyramid", &cv::BriskScaleSpace::constructPyramid );
}
Here I have wrapped the cv::BriskPatternPoint structure and the cv::BriskScaleSpace class. Some quick explanations:
class_< cv::BriskPatternPoint >( "BriskPatternPoint" ) tells boost::python to declare a class, using the cv::BriskPatternPoint C++ class, and expose it as BriskPatternPoint in python.
.def_readwrite("y", &cv::BriskPatternPoint::y) adds a readable & writeable property to the BriskPatternPoint class. The property is named y, and will map to the BriskPatternPoint::y c++ field.
class< cv::BriskScaleSpace >( "BriskScaleSpace", init< uint8_t >() ) declares another class, this time BriskScaleSpace but also provides a constructor that accepts a uint8_t (an unsigned byte - which should just map to an integer in python, but I'd be careful to not pass in one greater than 255 bytes - I don't know what would happen in that situation)
The following .def line just declares a function - boost::python should (I think) be able to determine the argument types of functions automatically, so you don't need to provide them.
It's probably worth noting that I haven't actually compiled any of these examples - they might well not work at all.
Anyway, to get this fully working in python it should just be a case of doing similar for every structure, class, property & function that you want accessible from python - which is potentially quite a time consuming task!
If you want to see another example of this in action, I did this here to wrap up this class
Building & using the extension
Visual studio should take care of building the extension - then using it is just a case of taking the .DLL and renaming it to .pyd (you can get VS to do this for you, but I'll leave that up to you).
Then you just need to copy your python file to somewhere on your python path (site-packages for example), import it and use it!
import brisk
patternPoint = brisk.BriskPatternPoint()
....
Anyway, I have spent a good hour or so writing this out - so I'm going to stop here. Apologies if I've left anything out or if anything isn't clear, but I'm doing this mostly from memory. Hopefully it's been of some help to you. If you need anything clarified please just leave a comment, or ask another question.
In case someone needs it, this what I have so far. Basically a BriskFeatureDetector that can be created in Python and then have detect called. Most of this is just confirming/copying what obmarg showed me, but I have added the details that get all the way to the pyd library.
The detect method is still incomplete for me though since it does not convert data types. Anyone who knows a good way to improve this, please do! I did find, for example, this library which seems to convert a numpy ndarray to a cv::Mat, but I don't have the time to figure out how to integrate it now. There are also other data types that need to be converted.
Install OpenCV 2.2
for the setup below, I installed to C:\opencv2.2
Something about the API or implementation has changed by version 2.4 that gave me problems (maybe the new Algorithm object?) so I stuck with 2.2 which BRISK was developed with.
Install Boost with Boost Python
for the setup below, I installed to C:\boost\boost_1_47
Create a Visual Studio 10 Project:
new project --> win32
for the setup below, I named it brisk
next --> DLL application type; empty project --> finished
at the top, change from Debug Win32 to Release Win32
Create main.cpp in Source Files
Do this before the project settings so the C++ options become available in the project settings
#include <boost/python.hpp>
#include <opencv2/opencv.hpp>
#include <brisk/brisk.h>
BOOST_PYTHON_MODULE(brisk)
{
using namespace boost::python;
//this long mess is the only way I could get the overloaded signatures to be accepted
void (cv::BriskFeatureDetector::*detect_1)(const cv::Mat&,
std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint>>&,
const cv::Mat&) const
= &cv::BriskFeatureDetector::detect;
void (cv::BriskFeatureDetector::*detect_vector)(const std::vector<cv::Mat, std::allocator<cv::Mat>>&,
std::vector< std::vector< cv::KeyPoint, std::allocator<cv::KeyPoint>>, std::allocator< std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint>>>>&,
const std::vector<cv::Mat, std::allocator<cv::Mat>>&) const
= &cv::BriskFeatureDetector::detect;
class_< cv::BriskFeatureDetector >( "BriskFeatureDetector", init<int, int>())
.def( "detect", detect_1)
;
}
Project Settings (right-click on the project --> properties):
Includes / Headers
Configuration Properties --> C/C++ --> General
add to Additional Include Directories (adjust to your own python / brisk / etc. base paths):
C:\opencv2.2\include;
C:\boost\boost_1_47;
C:\brisk\include;C:\brisk\thirdparty\agast\include;
C:\python27\include;
Libraries (linker)
Configuration Properties --> Linker --> General
add to Additional Library Directories (adjust to your own python / brisk / etc. base paths):
C:\opencv2.2\lib;
C:\boost\boost_1_47\lib;
C:\brisk\win32\lib;
C:\python27\Libs;
Configuration Properties --> Linker --> Input
add to Additional Dependencies (adjust to your own python / brisk / etc. base paths):
opencv_imgproc220.lib;opencv_core220.lib;opencv_features2d220.lib;
agast_static.lib; brisk_static.lib;
python27.lib;
.pyd output instead of .dll
Configuration Properties --> General
change Target Extension to .pyd
Build and rename if necessary
Right-click on the solution and build/rebuild
you may need to rename the output from "Brisk.pyd" to "brisk.pyd" or else python will give you errors about not being able to load the DLL
Make brisk.pyd available to python by putting it in site packages or by putting a .pth file that links to its path
Update Path environment variable
In windows settings, make sure the following are included in your path (again, adjust to your paths):
`C:\boost\boost_1_47\lib;C:\brisk\win32\bin`