Separate dll from other output files in c++ projects - c++

I have a few dll projects in a solution (some depending on each other)
Project1 -> Properties -> Linker -> Input -> Additional Dependencies -> Project2.lib
Project1 -> Properties -> Linker -> General -> Additional Library Directories -> $(OutDir)
All is working fine.
Projects are Win7Debug Win32, Win7Debug x64..... and a Win32 project with only Debug and Release configurations.
I would like to have all dll's for Win32 placed in one folder and the x64 ones in another folder. So I added the x64 configuration for the Win32 project, and changed
Project1 -> Properties -> Linker -> General -> Output File -> $(SolutionDir)/i386/$(TargetName)/$(TargetExt)
(for Win32 - similar change for x64)
all seemed fine - and I only received dlls in the i386 folder... until I had to rebuild and got
Warning 23 warning MSB8012:
TargetPath(C:\Path\Win7Debug\Project1.dll) does not match the Linker's OutputFile
property value (C:\Path\i386\Project1.dll). This may cause your project to build
incorrectly. To correct this, please make sure that $(OutDir), $(TargetName) and
$(TargetExt) property values match the value specified in %(Link.OutputFile).
This seems serious... and I don't want to have problems with missing dependencies (though everything seems to be working fine - and not just on my machine)
I changed
Project1 -> Properties -> Configuration Properties -> General -> OutputDirectory -> $(SolutionDir)/i386
(to match the linker output) but now of course I get lib and exp files in the same folder as the dll's.
Other than using post build script, is there a way to separate the output files ?
Should I just leave the settings how I had them and disregard the warning above ?
Note: I am not trying to separate the Platform/configuration output files... That is done automagically using the default output directory.
What I need is, for each platform, to place only DLL files in one folder away from anything else. Redirecting Linker output (and leaving project output to standard) accomplishes that - I just am not sure if it is correct. Logically I should not have any build problems since I am giving linker all the info it needs...

The standard approach is to leave all these properties unchanged (inherit from parent). In this case linker will create DLL and LIB in $(Output) directory, which by default is $(SolutionDir)$(Configuration).
You just specify the name for x64 configuration, and all output files will be separated automatically.
The standard (and the easest) way to link import library is to add reference to corresponding project in Common Properties / References page. Nothing else is required.
If, for any reason, it is impossible, add $(SolutionDir)$(Configuration) to Configuration Properties / VC++ Directories / Library Directories and add library to be linked to Linker / Additional Dependencies. If there are many projects in your solution, you may create Property Sheet for the solution and specify Library Directories only once.

Related

C++: Error occurs when fmt library is included

https://github.com/fmtlib/fmt
I'm having trouble using c++ library on ubuntu eclipse. I downloaded the fmt library from github. I followed the steps as described in the documentation section Building the Library. In fmt folder;
mkdir build # Create a directory to hold the build output.
cd build
cmake .. # Generate native build scripts.
After running the commands, makefiles are created in the build array.
To install the library I ran following command.
sudo make install
After the installation, the necessary files were copied to the /usr/local/ directory. I copied the header files and compiled libfmt.a file to my project directory.
My project hierarchy;
fmtTestProject
|--Debug
|--src
|--fmtTest.cpp
|--include
|--args.h
|--chrono.h
|--color.h
|--compile.h
|--core.h
|--format.h
|--format-inl.h
|--os.h
|--ostream.h
|--printf.h
|--ranges.h
|--std.h
|--xchar.h
|--lib
|--libfmt.a
I defined the include files to the eclipse project.
fmtTest -> Properties -> C/C++ Build -> Settings -> GCC C++ Compiler -> Includes -> Include paths -> "${workspace_loc:/${ProjName}/include}"
fmtTest -> Properties -> C/C++ Build -> Settings -> GCC C++ Linker -> Library search path -> "${workspace_loc:/${ProjName}/lib}"
After the define libraries, I wrote the code in the documentation and compiled it.
#include <fmt/core.h>
int main() {
fmt::print("Hello, world!\n");
}
The code compiles without errors. But the problem is there are too many errors for core.h file. Some errors;
Type 'std::experimental::basic_string_view<Char>' could not be resolved
Invalid overload of 'parse_format_specs'
Return has value, in function returning void
There are errors like these. The software compiles and runs, but there are errors in both main and library files. Likewise, I did the same compiling and installing to use the library named spdlog. It also compiles and works, but a lot of errors occur. Am I missing something in the cmake processes? There are always errors when I import an external library. How can I solve it?

Add OpenSSL static lib to Visual Studio 2017 project

Do NuGets modify the include and linking paths when added to a project?
My background is with CMake where this stuff was trivial, but I'm now at a company that builds solution files from the ground up and I'm unsure how to properly add the static OpenSSL libs to my project. I'm posting the question to make sure I don't duplicate something or otherwise mess it up.
When I add the openssl-vc141-static-x86_64 to my project, it builds the .lib files and everything, but does not modify the include or linker paths.
I can manually add the linker paths, but because the project I was given doesn't have the typical Release/Debug configurations, I can't use the $(Configuration) macro to point at the target libs - so I end of just pointing at Release. The build works though.
I see there is a .targets file, but it doesn't seem to do anything.
(update)
To be specific, I'm basically building boost's http_server_async.cpp. The linker errors I'm getting are:
Error LNK2019 unresolved external symbol _BIO_free referenced in function "public: __thiscall boost::asio::ssl::context::bio_cleanup::~bio_cleanup(void)" (??1bio_cleanup#context#ssl#asio#boost##QAE#XZ) ESOIPDataScope C:\gitrepo\ALIDB\ESOIPDataScope\DataHandler.obj
Error LNK2001 unresolved external symbol _BIO_free ESOIPDataScope C:\gitrepo\ALIDB\ESOIPDataScope\Listener.obj
... (48 more like this)
When I manually add $(SolutionDir)packages\openssl-vc141-static-x86_64.1.1.0\build\native\lib\Win32\static\Release\libcrypto.lib and
$(SolutionDir)packages\openssl-vc141-static-x86_64.1.1.0\build\native\lib\Win32\static\Release\libssl.lib to be additional dependencies the project compiles.
(/update)
Just for contrast, I added a freeglut NuGet, and noticed that gave my more configuration options (Configuration Properties → Referenced Projects), also, boost seems to have added its linker directories to my project (though I only see that in MSBuild output, not in Configuration Properties->Linker->Command Line)
Is there a proper way to add these projects that I'm missing? Or a proper way to use the targets file? Or maybe the OpenSSL static NuGet just missing something? Or maybe I should just look into vcpkg?
Do NuGets modify the include and linking paths when added to a
project?
Sure. I can tell you explicitly that the nuget imports additional properties into the project through <package_id>.targets or <package_id>.props file, instead of manually adding include path again.
This is a mechanism for nuget packaging to add additional project properties such as library path directly to the project during the installation of the nuget package. More info you can refer to this link.
The <package_id>.targets was created during the process of packing the nuget package.
In other words, this method was designed by the author of the nuget package. And in my side, the file openssl-vc141-static-x86_64.targets exists in this path:
C:\Users\Admin\source\repos\ConsoleApplication25\packages\openssl-vc141-static-x86_64.1.1.0\build\native
also, boost seems to have added its linker directories to my project
(though I only see that in MSBuild output, not in Configuration
Properties->Linker->Command Line)
l think the issue is related to the difference between <package_id>.targets and <package_id>.props. Although using <package_id>.targets does not appear on the property UI, it still works for the whole project.
In more detail
When you install the nuget package into the project, these files are automatically executed. <target_id>.props file is added at the top of the file while .targets is added at the bottom.
When initializing the xxx.vcxproj file, because <package_id> .props is at the head of the file, the property UI can capture the properties in the file, and <package_id> .targets is at the end, so the initialization cannot be captured but still In the project. For the nuget, it uses openssl-vc141-static-x86_64.targets.
In openssl-vc141-static-x86_64.targets file, you can see this:
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include\;%
(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAS_LIBTHRIFT;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
And l have set the output log to Diagnostic and build the project and found this:
The library path has been added into AdditionalIncludeDirectories by the openssl-vc141-static-x86_64.targets file automatically. So you do not have to worry about it.
Is there a proper way to add these projects that I'm missing? Or a
proper way to use the targets file? Or maybe the OpenSSL static NuGet
just missing something? Or maybe I should just look into vcpkg?
You do not need to worry about it and do not add the include path into project property. This is superfluous and when you have finished installing this nuget package, use it in cpp files directly.
In addition,
For c++ packages installed by nuget, you don't need to add any paths to the project property.
Update 1
The issue is related to your project rather than the nuget package. Exactly because your current project does not have $(Configuration), so in openssl-vc141-static-x86_64.targets, you can see these:
<ItemDefinitionGroup Label="Win32 and vc141 and Debug" Condition="'$(Platform)' == 'Win32' And ( $(PlatformToolset.IndexOf('v141')) > -1 Or '$(PlatformToolset)' == 'WindowsKernelModeDriver8.0' Or '$(PlatformToolset)' == 'WindowsApplicationForDrivers8.0' Or '$(PlatformToolset)' == 'WindowsUserModeDriver8.0' ) And '$(Configuration)' == 'Debug'">
<Link>
<AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)lib\Win32\static\Debug\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /Y "$(MSBuildThisFileDirectory)\lib\Win32\dynamic\*-1_1.dll" "$(OutDir)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
This is the operation to import specific libssl.lib and libcrypto.Lib into the AdditionalDependencies node. But you can find out that there is a judge condition And '$(Configuration)' == 'Debug', since you do not have $(Configuration),therefore, it always returns false and these libs cannot be automatically imported into AdditionalDependencies.
As a workaround, you should add these lib path manually just as you said.
And l am sure that if you use a project which contains $(Configuration)(Debug or Release), you will not encouter this issue. And most of the C++ nuget packages can be used directly in the project which contains the Configuration node.
l am sure that if you use the $(Configuration) into your project and then reinstall this package(please clean the nuget cache before doing it), you will not face this error.
Also, your screen shot, where did you get that? I don't see anything
like that in the VS output console, or when I run msbuild on the
command line. Is there some way I might have accidentally broken the
default behaviour?
You can set MSBuild project build output verbosity to Diagnostic by Tools-->Options-->Projects and Solutions-->Build and Run.
When you build your project,the Output Window shows thw whole build process and records all the information and then you can search the key fields by the search box on the Output Window.

Changing the launch directory of executable in MSVC

My folder hierarchy looks like this:
bin -> data -> blurf.xml
lib -> blurb.lib
src -> blah.cpp
msvc -> project_name -> project_name.sln ...
....
Here is my issue. This project needs to run on Linux and Windows
So I need that when I build it in MSVC, the exe ends up in ../../bin
This is because my application has a data folder and the application expects to find in the root where the exe is.
Is there a way that when I run a build, it thinks it is (or is) in the ../../bin directory so it accesses the data folder?
If not, is there some other way I can have it know where its data is when I run from MSVC?
Go to project properties, Debugging sheet and set 'Working directory' accordingly

VS2012(C++) Project: can't set "Link Library Dependencies" to True

So I am trying to set the static lib projects for my main project so that I don't need to specify the folder with the .lib file. I read here how to do it.But when I set "Framework and References" -> "Link Library Dependencies" to "True" and click "Apply" it gets reset to "False". Why?
UPDATE:
As Hans Passant explained,those settings exist only for a mixed mode.But what I don't understand then,why in my case as long as "Link Library Dependencies" was set to false the libs wouldn't link automatically?Finally,btw,I was able to set it to True by removing and adding those libs back as reference and Setting Linker->General->Link Library Dependencies -YES .Now I don't need to explicitly specify lib paths in linker for these libs.But again,I am not sure that's the way to go?

With Eclipse: How to add include paths and libraries for all your C/C++ project

Is it possible to add include paths and libraries to all C/C++ projects? In others words: How can I make them global or copy one C/C++ project build setting to another one?
For Eclipse Indigo:
There is no possibility to define globally include paths and libraries.
But you can export and import them from one project to another.
Go to Project > Properties > C/C++ General > Paths and Symbols
Then click Export Settings... to save the include paths and/or symbol definitions to a file. In your other project, you can then use Import Settings...
Yes, you can, in 2 steps, more user-friendly as the one mentioned by parvus. Both are done in "Project Properties" -> "C/C++ General" -> "Paths and Symbols":
In an existing project where you've already configured the include paths: Highlight the include paths (in the tab "Includes") which you want to copy to the new project and choose "Export". Note that this adds an [Exp] tag to each line.
In the new created project: In the "References" tab, tick the checkbox of the just mentioned project and when you switch back to the "Includes" tab, you see that all the paths you've just exported appear there.
Referencing the libraries works the same way.
Also have a look at:
the Eclipse Juno Documentation to this topic,
a related StackOverflow question
I often use the CPATH environment variable to include different directories across all my projects. It's found under: c/c++->build->environment.
Be sure to separate each path with a ':' character (not a ';' semicolon).
You can also use PATH to include static libs. However, for me it's only worked reliably in linux. In OSX it ruins make.
The alternative would be to add these libraries and headers to your environments default search paths; place likes /usr/local/lib. Read up on where your linker searches by default.
For libraries I do the following in the source project:
Project -> properties -> c/c++Build -> c++ linker -> libraries
After this I select libraries (shift + mouse) & copy (ctrl + c)
In the blank project:
Project -> properties -> c/c++Build -> c++ linker -> libraries
ctrl + v (paste)
Works fine with eclipse juno
I just copy one project from using eclipse built in Project explorer. Afterwards, just rename source files.
I am looking into it long ago.
A few posts mentioned one method:
Project > Properties > C/C++ General > Paths and Symbols Then click Export Settings..
But it only works for including header files.
To specify libraries and library paths, as far as I know, I do not find an easy solution.
For example, I am now using ffmpeg libraries.
If you use "Makefile", the including and library files can be expressed below:
FFMPEG_LIBS= libavdevice
libavformat
libavfilter
libavcodec
libswresample
libswscale
libavutil
CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS
:= $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS)
There are many files here.
If I include them one by one in an Eclipse C++ project, it is daunting.
I do not know why there is no option in Eclipse that we could include library files by using past a long line using ; as a separator, such as:
-lavdevice -lavfilter -lswresample -lswscale -lavformat -lavcodec -ldl -lasound -lSDL -lz -lrt -lavutil -lm
Is there any such way, or I have to type the library files one by one, or have to use Makefile?
I faced the same problem and solved it like this :
I saw that in the auto-generated makefile there are lines:
-include ../makefile.init
...
-include ../makefile.defs
...
-include ../makefile.targets
after reading How can I parameterize an Eclipse generated make file I realized that you can define variables outside of you project. That mean it can be shared variable to several projects. So I added makefile.defs file outside of the project and declare in it some variables:
MY_INCLUDE = <path to include>...
MY_LIBS_PATH = <path to libs>...
MY_LIBS = -lmylib ... (the libs)
than in all my projects "properties->c/c++ build->build variables" I defined new variable:
my_include = $(MY_INCLUDE)
my_libs_path = $(MYLIBS_PATH)
my_libs = $(MY_LIBS)
And than you can you those variables in the projects. Go to properties->c/c++ build->Settings and choose compiler includes and add $(my_include). Go to linker and choose Libraries and add to search path $(my_libs_path). For some reason the Libraries (-l) can't take my defined env variable so I bypass it by choosing linker and than go to Miscellaneous and add to linker flags $(my_libs). Finally you have to change the order in the command line (when the linker execute) cause the list of libs need to come after the .o files. So to do that you go to linker and tab and there you can see the final command line that is going to be executed. In "expert settings command line pattern" you move the ${FLAGS} to the back of the command line (that moves the $(my_libs) string to be in the back of the command line). THAT ALL. its a lot but you need to do it only once... hope that it helps someone...
Semi-automagically, it can be done using this perl script:
#!/usr/bin/perl
# pipe the (gcc) compile command into this script
# It emits listOptionValue lines to paste into .cproject
#
# To easily find the paste location, set the include path as usual to a string
# that is easily recognizable in the .cproject, e.g. to "MARKER_INCLUDE_PATH".
#
# Make sure eclipse is not running while you do these sorts of hacks and backup
# your .cproject before.
# -----------------------------------------------------------------------------------------
# sample line: <listOptionValue builtIn="false" value="/usr/include/gdk-pixbuf-2.0"/>
while (<>) {
#include_options = m#-I *(.*?) #g;
print join ("\n", #include_options) . "\n";
print join ('"/>' ."\n" . ' <listOptionValue builtIn="false" value="', #include_options);
print '"/>' . "\n";
}