As part of the build process we produce two executables from our source exe1 and exe2. These executables link in a static library which has to have some extra code run in the case of exe2 so the static library has the following code (changed for brevity).
#ifdef _EXE2_
Do certain stuff
#endif
now our CMakeLists.txt defines two targets exe1 and exe2, I tried the following change so that __EXE2_ would get defined only for exe2
target_compile_definitions(exe2 PUBLIC _EXE2_)
however it seems to me that the above line just adds this definition to exe2 and the static lib does not get that definition. Is there a way around this? or do i have to solve this with an exe configuration file. This is c++ code on linux if that helps in any way.
Why would it? The exe depends on the library, not the other way around. Generally, a library has no relation to the modules that include it.
A library is also built once regardless of how many applications include it. That's the whole point of having a library.
If you want you can just add the definitions globally in your main CMakeLists.txt:
add_compile_definitions(_EXE2_)
Note that identifiers beginning with an underscore followed by an uppercase letter are reserved and should not be used.
Related
I'm (cross-)compiling a shared C library with support for many different platforms which is handled by an hierarchy of CMakeLists files. In those files, several platform specific compiler flags are conditionally produced (with add_definitions()). I can successfully compile and link the source code leading to an appropriate .so file.
But to use the library in any project, I need to provide the right header files, too. The following install command of CMake selects the right header files to copy but does not apply the replacement of preprocessor defines/includes:
install(FILES ${headers} DESTINATION include/mylibrary)
So how can I generate/install the "post-compiled" header files?
What I thought of so far:
As add_definitions() should stack my -D's in the COMPILE_DEFINITIONS variable, maybe running a foreach loop on the copied raw headers and replace the define/include placeholders?
Using add_custom_command() to apply some logic before copying?
Edit: As pointed out by Tsyvarev, there is an answer quite near to my needs here, but unfortunately not quite it. In summary, the answer gives 2 options:
Include a special 'config' header in all of the library's headers and leverage the cmakedefine command to call configure_file() on this header. I can't use this approach because I don't want to alter the library headers.
Create a target-specific .cmake file which helps external projects in including the right headers together with all necessary -D defines. I can't use this approach either, because my external projects do not use cmake for building. Plus, I wish to create a library that is as easy to include as possible.
Any other thoughts?
Edit 2: I may have to elaborate on my statement, that the install command of CMake is not replacing defines. Take the following example:
//sampleheader.hpp
#ifndef SAMPLEHEADER_HPP_
#define SAMPLEHEADER_HPP_
#include OS_SPECIFIC_HEADER
//...
Now I have a CMakeLists.txt file that does something like this:
# ...
if (${OS} MATCHES "arm-emblinux")
add_definitions(-DOS_SPECIFIC_HEADER="emblinuxHeader.hpp")
elseif (${OS} MATCHES "linux")
add_definitions(-DOS_SPECIFIC_HEADER="linuxHeader.hpp")
endif()
# ...
Everything compiles fine, but when the install command above gets called, I have a header file in my ../include/ directory still with OS_SPECIFIC_HEADER placeholder in it. And of course, this cannot be properly included in any development project.
I would like to compile a static library out of all the functions I have written for a C++ project. I am using CodeLite 11.0.0 on Ubuntu 16.04, configured to use GCC as compiler.
I have followed the instructions in CodeLite's tutorial, according to which this should be possible, and changed the project type from Executable to Static Library.
After running the project (CTRL+F5 command), I expected to find a .a file in the /Debug folder, either along with, or in place of the executable file. All I could find, though, was the executable and a number of .o and .o.d files. The same I was finding when the project was set to Executable.
I tried to close and reopen CodeLite, but it did not help. I can't find any official/unofficial example of how to build a static library with CodeLite.
Does anyone know how to set-up CodeLite to produce a .a static library file?
As you've probably discovered, CodeLite allows you to change the type of a
project in the drop-down menu from Settings -> General -> Project type.
Doing so, however, does not change the name of the project target. So, if
you started off your project as an executable myprog - from which, say, the
Debug build generated ./Debug/myprog under the project folder - then
you change the project type to static library and rebuild it, the Debug
build will still generate ./Debug/myprog, but that file will now in fact
be a static library, lacking the customary lib-prefix and .a extension.
To give the output file a conventional static library name -
libmyprog.a - you need to go back into Settings -> General and
change Output File from:
$(IntermediateDirectory)/$(ProjectName)
to:
$(IntermediateDirectory)/lib$(ProjectName).a
Then rebuild the project and it will output a target that is a static
library and looks like one.
Of course, you must make the same changes to the project settings in both
the Debug and Release configurations if you want them both to produce
targets with the same file type and file name.
However...
If this way of converting a program project to a static library project does not
seem very slick, that could be because it is a conversion of very little use.
The static library produced after the conversion will contain exactly the same object
files that the program was built from, including the object file that defines
the main function of the original program. Let's suppose that object file
is main.o, and that it defines 0 or more other functions that the linker can see.
Any other program, newprog, that is linked with the static library must provide
its own main function in a different object file, so in any such linkage one of
two things must happen:-
The linkage of newprog does not need any function defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is not linked and might as well not exist.
The linkage of newprog does need some function, foo, defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is linked; then as well as the definition of foo, the
program links duplicate definitions of main - its own definition plus the
one in libmyprog.a(main.o). Duplicate definitions are an error, so the linkage fails.
Putting a definition of some program's main function into a member of a static
library is pointless, because if that member is ever needed in the linkage of another
program then its linkage will fail.
So converting your program project to a static library project calls for some
refactoring prior to the conversion:-
If any function that you want in the static library is defined in the same source
file as main, then you need to take it out of that source file and define it
is a different one.
After that, remove the source file that defines main from the project.
Lastly, convert and rebuild the project.
You have to do that refactoring to extract from your original program source code
a bunch of source files that are suitable for building into a static library.
Assuming you've done that, the straightforward way to create a static library with
CodeLite is to create a project for that purpose and in the New Project Wizard
choose Library -> Static Library as the project type instead of some kind
of executable.
Then just add either new or existing source files to the static library project
until it contains definitions of all the functions you want the library to
provide. Build, test, debug, edit... until done.
For example in Boost. I set an include directory in MSVC++2010 to the Boost root directory and have an #include <boost/regex.hpp> in my source code. I set a library directory to boost\stage\lib but there are hundreds of files in there – several for each Boost library and these for boost::regex:
libboost_regex-vc100-s-1_46.lib
libboost_regex-vc100-mt-gd-1_46.lib
libboost_regex-vc100-mt-1_46.lib
libboost_regex-vc100-mt-s-1_46.lib
libboost_regex-vc100-mt-s.lib
libboost_regex-vc100-s.lib
libboost_regex-vc100-mt.lib
libboost_regex-vc100-mt-gd.lib
How does MSVC know which of all lib files is the right one? If it scans all of them for the right function signatures, does that mean that 2 different lib's compiled from two different sources (not linked to each other) which happen to define functions with identical names and parameters cannot be in one lib folder?
And how does it know which is right among all those different regex .lib's? And then, each file with 1_46 in its filename seems to be identical to the respective file without, can I safely delete one of the two?
The boost libraries use some dark magic to select the libraries to link from the headers and compiler options. I don't really know all the gory details, but you can take a look at the boost/config/auto_link.hpp header for extra information.
In particular, this seems to be an important piece of the puzzle:
# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")
Most lib files have a Table Of Contents. The linker searches this table when it is looking for a symbol. If the symbol is not found it moves on to the next library, and so on, until all libraries have been searched.
Some linkers may decide to build a table of contents from all the libraries. This table would contain the symbol name and the library it is associated with. This speeds up the searches for symbols.
The search order depends on the manufacturer of the linker. There is no standard nor requirements for this. A linker may search by first come, first served as specified on the command line; last library specified or some other method. Check the documentation for the criteria.
Also search the web for name mangling. This is a technique that compilers use to resolve symbol naming conflicts.
Lastly, linkers may include all the functions in a library even if only one is used. Some linkers only include the code for the function. Depends on the manufacturer of the Linker. For example, does the linker include the entire I/O library when resolving puts or does it just include the necessary functions? Including the whole library speeds up build time but makes the executable huge. Including only necessary code slows the build process but shrinks the executable size.
In general, the Linking Phase is one of the faster parts of the translation process. If you are worried about build times, start the build at the end of the day or go for a walk after the build is started. ;-)
Two libraries containing identical functions isn't a problem. The linker only looks at the libraries that it's told to look at. If two of them contain identical functions, it'll give an error message (this is actually fairly common, usually due to conflict between static and dynamic linking with the standard library).
You can tell the linker which libraries to look at in a number of ways -- on the linker command line (possibly as generated by the IDE) and via #pragma comment(lib, "libname.lib") are the two most common though.
I've got a CMake project that includes and links against two libraries, say A and B (actually it's more than two and one of them is boost stuff, but that doesn't really matter here). Both are located via FindSomething.cmake scripts that (correctly) populate the standard CMake variables such that include directories are added via
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})
and linking is later done via
TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})
Now, the problem is that both libraries can either reside in a user based location or in the system directories (I'm on linux by the way, CMake 2.8.2) - or in both. Let's say A is only in $HOME/usr/include and $HOME/usr/lib while B (boost in my case) resides in both the system paths (/usr/include and /usr/lib) AND in the user based paths - in different versions. The find scripts can be made to find either the system or the user-based library B, this works.
The trouble starts when I want to link against B from the system paths.${B_INCLUDE_DIRS} and ${B_LIBRARIES} correctly point to the system-wide locations of the headers and libraries. But there is still ${A_INCLUDE_DIRS} that points to a non-system include directory and ultimately also the headers for library B are taken from this location, while the linking for B uses the version from the system paths (via ${B_LIBRARIES}) which leads to conflicts, i.e. linking errors.
Changing the order of the INCLUDE_DIRECTORIES statements does not seem to change anything. I checked the origin of the symbols that cause the linking errors via nm --line-numbers on the object files.
What can I do? Is there a trick to
force the ordering of the include directories (even if this would mean to give precedence to a system path although there is also a user-based location specified)?
tell CMake to use ${A_INCLUDE_DIRS} for all headers from A and ${B_INCLUDE_DIRS} for all headers from B?
Here's what CMake says about include_directories():
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
You can specify that you want to have include directories searched before or after the system include directories at the time that you tell it about those directories.
You may also be specific to a target:
target_include_directories(target [SYSTEM] [BEFORE] [items1...] [ [items2...] ...])
If A and B are different libraries containing different header files and paths, there should be no problem doing what you are doing right now.
That being said, if A and B are similar libraries containing header files of the same name at the same location, that is problematic. In that case, the order of the include_directory() call is important. I ran a little test where I had three copies of a header file. The first copy is located in my system path (say /usr/include). The other copies are located in two user-defined locations (say /tmp/include1 and /tmp/include2). The file in /tmp/include1 is found and used first if I put the include_directory() call in the following order:
include_directory("/tmp/include1")
include_directory("/tmp/include2")
The file in /tmp/include2 is found and used first if I put the include_directory() call in the following order:
include_directory("/tmp/include2")
include_directory("/tmp/include1")
If I put no include_directory() statement, then the header in the system path is found and used.
You may want to re-check how your FindSomething.cmake are written. The search order of the find_*() CMake commands can be found in the CMake documentation,
As far as I can remember, there is now way of telling CMake to use ${A_INCLUDE_DIRS} for all headers from A and ${B_INCLUDE_DIRS} for all headers from B if the header file can be found in both location. It all depends in what order the include_directory() call are made. If the FindSomething.cmake are written properly, if the CMAKE_MODULE_PATH (this is the location where CMake will look for the Find*.cmake files) is set properly and all the paths are good, then you should be good to go. If not, I will need more information on your current CMake/library setup.
When using third party libraries, I would always do this
Library A + B header files:
third_party/include/libA_name/ <-- put header files in there
third_party/include/libB_name/ <-- put header files in there
In source files you would always use it like this
#include "libA_name/file.h" <-- no ambiguity possible
#include "libB_name/file.h" <-- no ambiguity possible
Then you can still use -I "third_party/include" as the include folder and no ambiguity in ordering will happen in source files.
This also disambiguates custom header files from system header files which could clash from time to time from 3rd party libs.
For me this worked fine:
INCLUDE_DIRECTORIES(BEFORE ${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})
I am creating a project that uses a DLL. To build my project, I need to include a header file, and a lib file. Why do I need to include the respective lib file? shouldn't the header file declare all the needed information and then at runtime load any needed library/dll?
Thanks
In many other languages, the equivalent of the header file is all you need. But the common C linkers on Windows have always used import libraries, C++ linkers followed suit, and it's probably too late to change.
As a thought experiment, one could imagine syntax like this:
__declspec(dllimport, "kernel32") void __stdcall Sleep(DWORD dwMilliseconds);
Armed with that information the compiler/linker tool chain could do the rest.
As a further example, in Delphi one would import this function, using implicit linking, like so:
procedure Sleep(dwMilliseconds: DWORD); stdcall; external 'kernel32';
which just goes to show that import libraries are not, a priori, essential for linking to DLLs.
That is a so-called "import library" that contains minimal wiring that will later (at load time) ask the operating system to load the DLL.
DLLs are a Windows (MS/Intel) thing. The (generated) lib contains the code needed to call into the DLL and it exposes 'normal' functions to the rest of your App.
No, the header file isn't necassarily enough. The header file can contain just the declarations of the functions and classes and other things you need, not their implementations.
There is a world of difference between this code:
void Multiply(int x, int y);
and this code:
void Multiply(int x, int y)
{
return x * y;
}
The first is a declaration, and the second is a definition or implementation. Usually the first example is put in header files, and the second one is put in .CPP files (If you are creating libraries). If you included a header with the first and didn't link in anything, how is your application supposed to know how to implement Multiply?
Now if you are using header files that contain code that is ALL inlined, then you do not need to link anything. But if even one method is NOT inlined, but has its implementation in a .CPP file that is compiled to a .lib file, than you need to link in the .lib file.
[EDIT]
With your use of Import Libraries, you are telling the linker to NOT include the implementation details of the imported code into your binary. Instead the OS will then load the import DLL at run-time into your process. This will make your application smaller, but you have to ship another DLL with it. If the implementation of the library changes, you can just reship another DLL to your customers, and not have to reship the entire application.
There is another option where you can just link in a library and you don't need to ship another DLL. That option is where the Linker will include the implementation into your application, making it bigger in size. If you have to change the implementation details in the imported library, then you have to recompile and relink your entire application, and reship the entire thing to your customers.
There are two relevant phases in the building process here:
compilation: from the source code to an object file. During the compilation, the compiler needs to know what external things are available, for that one needs a declaration. Declarations designed to be used in several compilation units are grouped in header. So you need the headers for the library.
linking: For static libraries, you need the compiled version of the library. For dynamic libraries, in Unix you need the library, in windows, you need the "import library".
You could think that a library could also embed the declarations or the header could include the library which needs to be linked. The first is often done in other languages. The second is sometimes available through pragmas in C and C++, but there is no standard way to do this and would be in conflict with common usage (such as choosing a library among several which provide code variant for the same declarations, for instance debug/release single thread/multithreads). And neither choice correspond well with the simple compilation model of C and C++ which has its roots in the 60's.
The header file is consumed by the compiler. It contains all the forward declarations of functions, classes and global variables that will be used. It may also contain some inline function definitions as well.
These are used by the compiler to give it the bare minimum information that it needs to compile your code. It will not contain the implementation details.
However you still need to link in all the function, and variable definitions that you have told the compiler about. Failure to do so will result in a linker error. Often this is contains in other object files which may be joined into a single static library.
In the case of DLLs (or .so files), we still need to tell the linker where in the DLL or shared object the missing symbols are. On windows, this information is contained in a .lib file. This will generate the code to load and link the code at runtime.
On unix the the dll and lib files are combined into a single .so file which you must link against to about linker errors.
You can still use a dll without a .lib file but you will then have to load and link in all the symbols manually using operating system APIs.
from 1000 ft, the lib contains the list of the functions that dll exports and addresses that are needed for the call.