I have a file which looks something like this:
#include <Shlwapi.h>
...
void SomeFunction()
{
UrlCombineW(...)
}
This compiled just fine until I installed another Delphi component in C++ Builder IDE but now reports unresolved external for UrlCombineW. The above call was fine before installing this component.
It seems that the component is overwriting this in some way so I need to explicitly tell the compiler where to look for UrlCombineW. This is a function from Shlwapi.dll.
Compiler does not complain, but how do I explicitly tell the linker where to look for this function and avoid unresolved external error?
Expanding my comment to an answer.
You need to link to Shlwapi.lib in order for the linker to find the functions. (This explanation glosses over a few things, but a .lib, a library file, can be either a static or import library. A static library contains the functions themselves - it's basically a collection of .obj files bundled together; an import library says that functions X, Y and Z are found in a specific DLL.) Either way, if you link the .lib in you will get the functions that you need.
There are a couple of ways to do tell the linker to link in the file:
Use #pragma comment(lib, "Filename.lib") in a .cpp file somewhere. For your case, this is #pragma comment(lib, "Shlwapi.lib").
Add it to the project options, which in turn adds it to the linker command line. In C++ Builder you do this by actually adding the .lib file to the project, ie drag and drop it onto the project in the Project Manager, or use File > Add To Project.
Which you prefer is up to you. I tend to link to localized things locally - so in my code, there's only one unit which uses Shlwapi.h and the fact it does so is an implementation detail hidden from the outside, it's not shown in the interface. Therefore, in that file, I link using #pragma comment at the point I include the header. On the other hand, if you have something used far more widely - to pick the widest example, kernel32.lib - I would add that the project itself. (Note this is an example, you don't actually need to explicitly link to kernel32, that will be done for you!)
Related
If an identifier is defined in the current dart file, then that identifier shadows elements with the same identifier that are defined in other files included using the import directive. When using such an identifier in the current file, no errors occur, the version from the current file is used.
If some id is defined in file 1 and file 2, but is not defined in the current file, then an error will occur when trying to apply the identifier, which can be eliminated by using import prefixes or show, hide commands.
The logic described above is clear. But when working with the dart:core library, the following error may occur. Let's consider the cause of the error using the print function as an example.
If the print function is not defined in the current file and that function is defined in one of the import files, then the dart:core version of the library will be grayed out. No compilation errors that require an import prefix or the show/hide command will be generated.
The described situation can lead to confusion. The same applies to some other dart:core libraries. There are examples below.
// test2.dart
void print() {
}
// test.dart
import 'test2.dart';
void main() {
// some useful function from test2.dart
print2();
// static error due to inappropriate argument types,
// not due to collision with print function from dart:core
print('work is done');
}
This error persists when explicitly including the dart:core file.
In connection with what has been said, there are the following questions.
Will the dart developers read my message, or where do they need to forward it to read it?
Is this really a bug or was it meant to be? I propose to correct it so that the language is more simple and understandable.
I expected that if an identifier in one of the files matches an identifier from the dart:core library, the behavior will be the same as if a simple other package, file.
The rules for name conflicts are special for names coming from platform (dart:) libraries.
Normally if you import different declarations with the same name through two different imports, it's a conflict. You get an error if you try to refer to the name, because the compiler cannot figure out which one you mean.
However, if you import different declarations with the same name, and some, but not all, come from dart: libraries, then the declarations from the dart: libraries are ignored, and the non-platform libraries take precedence. (And if there is only one declaration from a non-dart: library, it just works as normal.)
The reason for this exception is that Dart libraries typically come from packages, where you can control which version of the library you get.
You won't get new declarations without doing a dart pub update or similar. That means that a new name conflict are only introduced at times where you are actively developing, and you can then handle.
Platform libraries come from the SDK, and your SDK can be updated independently of the packages you are working on. Even if you tested your application thoroughly and locked all your dependencies to specific version that you know will work, it might end up being run on a newer SDK.
Because of that, adding new declarations to the platform libraries was considered more dangerous than adding them to normal packages. To avoid it being practically impossible to add anything to the platform libraries, it was instead decided to not make such new conflicts into errors.
If the platform libraries introduce a new declaration, it should not affect your imports. It won't introduce a new conflict.
(It can cause other errors, because no API change in Dart is ever entirely safe, but at least it won't cause import conflicts.)
I need to add headers to an already existing program by transforming it with LLVM and Clang.
I have used clang's rewriter to accomplish a similar thing in the changing function names and arguments, etc.
But the header files aren't present in clang's AST. I already know we need to use PPCallbacks (https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html) but I am in dire need of some examples on how to make it work with the rewriter if at all possible.
Alternatively, adding a #include statement just before the first
using namespace <namespace>;
Also works. I would like to know an example of this as well.
Any help would be appreciated.
There is a bit of confusion in your question. You need to understand in details how the preprocessor works. Be aware that most of C++ compilation happens after the preprocessing phase (so most C++ static analyzers work after that phase).
In other words, the C++ specification (and also the C specification) defines first what is preprocessing, and then what is the syntax and the semantics of the preprocessed form.
In other words, when compiling foo.cc your compiler see the preprocessed form foo.ii that you could obtain with clang++ -C -E foo.cc > foo.ii
In the 1980s the preprocessor /lib/cpp was a separate program forked by the compiler (and some temporary foo.ii was sitting on the disk and removed at end of compilation). Today, it is -for performance reasons- some initial processing done inside the compiler. But you could reason as if it was still separate.
Either you want to alter the Clang compiler, and it deals (like every other C++ compiler or C++ static analyzer) mostly with the preprocessed form. Then you don't want to add new #include-s, but you want to alter the flow of AST given to the compiler (after preprocessing), and that is a different question: you then want to add some AST between existing AST elements (independently of any preprocessor directives).
Or you want to automatically change the C++ source code. The hard part is determining what you want to change and at what place. I suppose that you have used complex stuff to determine that a #include <vector> has to be inserted after line 34 of file foo.cc. Once you've got that information (and getting it is the hard thing), doing the insertion is pretty trivial. For example, you could read every C++ source line, and insert your line when you have read enough lines.
BACKGROUND
I'm building an iOS app (which I'll just call MyApp from here) that will rely on calculations done by several separate static libraries (which I'll call Lib1, Lib2, Lib3,...). Each library is built in it's own project, then imported into a single workspace (so the workspace will contain MyApp, Lib1, Lib2, ...). More details on how this is set up here. The libraries are used by other products that are independent from MyApp, so I want to minimize any changes in the libraries. The libraries are also written in (plain) C, so there are no header files.
Certain function names are used by multiple libraries (so both Lib1 and Lib2 might each have a DoStuff method). Functions with the same name generally do the same thing, but there are some specifics about how that do it that can be different between libraries, so the actual code in DoStuff on Lib1 might be quite different than the code in DoStuff on Lib2. It would be very difficult to write one universal DoStuff that would be exactly the same in each library.
THE ISSUE
While the app is running, it isn't calling the correct DoStuff from the correct library. I found out about this because the wrong function was called during a debug session (which eventually caused the app to crash, due to the subtle differences in the DoStuff functions).
WHAT I'M LOOKING FOR
Each library has only one entry point from MyApp, and each entry point is uniquely named. If DoStuff is called from the entry point method of Lib1 (or any other method on Lib1, for that matter), then I want it to call the DoStuff method on Lib1. What's the best way to make that happen?
Is there any way (maybe through a setting somewhere in XCode) I can make it so that each library is it's own namespace? That would be my preferred way to fix the issue. I guess I could go through and rename the duplicate functions so that they are all unique (so the DoStuff method on Lib1 could be renamed to Lib1DoStuff, or something similar), but there are hundreds of functions that could have duplicate names, and we are going to be adding hundreds of libraries to the project, so having to go in and rename all the functions by hand and fix all the calls to them would take a significant amount of time, and my boss doesn't see that as a viable option.
UPDATE
After looking at the comments from Josh Caswell and some of the links he provided, it looks like it might be possible to automatically rename all the functions when the libraries are compiled, and that would be the best way to try to fix THE ISSUE above. From what I've seen, the objcopy that gets mentioned in a couple of the links in the comments isn't support on iOS. I eventually came across this blog entry, which talks about creating custom build rules for Xcode targets, and this blog that talks about custom build settings and build phases.
Am I right to assume that I can use scripts at some point in the build process to automatically append to the name of all the functions in each of my libraries, instead of doing it manually as I described in the last paragraph of the WHAT I'M LOOKING FOR section above? If so, which is the correct part of the build process to make those changes? Lastly, what would the syntax look like for doing something like that? The 'scripts' used in the different parts of the build processes certainly doesn't look like Obj-C. I've never used these 'scripts' before, so I'm completely in the dark on how I'd use them, and that's what I'm looking for help with.
I tried to be as clear as I could, but if there are any questions on what I'm asking please let me know.
Why isn't xcode calling the correct library function?
Let's say I have 3 C libraries as mentioned by you. Let's say it has the following code.
Library 1 - test1lib.a with code:
#include <stdio.h>
void doStuff()
{
printf("\nDoing stuff for lib1\n");
}
void uniqueEntryPoint1()
{
printf("\nUnique entry point for lib1\n");
doStuff();
}
Library 2 - test2lib.a with code:
#include <stdio.h>
void doStuff()
{
printf("\nDoing stuff for lib2\n");
}
void uniqueEntryPoint2()
{
printf("\nUnique entry point for lib2\n");
doStuff();
}
Library 3 - test3lib.a with code:
#include <stdio.h>
void doStuff()
{
printf("\nDoing stuff for lib3\n");
}
void uniqueEntryPoint3()
{
printf("\nUnique entry point for lib3\n");
doStuff();
}
Here each library has a unique function and one common function doStuff()
When we add these 3 libraries to xcode and link them. xcode links but does not load all the objects files. Let's say the objective C code is like this:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
uniqueEntryPoint1();
}
The output is
Unique entry point for lib1
Doing stuff for lib1
In this case xcode will only load symbols which are referred (library 1 objects) in this case.
If you are read about linker flags/options such as -all_load, -force_load and -objC, you will have better understanding.
If we add -all_load linker option, it will force linker to load all the objects of libraries so we will get the following error in xcode
ld: 2 duplicate symbols for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The reason this fails as the linker detects that doStuff() is redefined multiple times.
The only way around this problem is change the linker input i.e. symbols present in these 3 libraries. This is already mentioned by Josh in the comments. I will add my $0.02 to it.
Possible Solutions
Solution 1:
The best solution (self explanatory) is to change the source code if you have access to the same.
Solution 2:
Use objcopy to rename or prefix the function as provided in the answer of this How to deal with symbol collisions between statically linked libraries?
Now your doubt on how to find the objcopy.
Option 1:
You can use this project https://github.com/RodAtDISA/llvm-objcopy. This will be tricky to compile as it builds along with llvm. You will have to follow instructions at http://llvm.org/docs/GettingStarted.html and http://llvm.org/docs/CMake.html.
If you rewrite the https://github.com/RodAtDISA/llvm-objcopy/blob/master/llvm-objcopy.cpp, you can probably reuse the parsing and object rewriting logic without depending upon llvm.
Option 2:
Compile and reuse binutils objcopy from https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=binutils/objcopy.c;h=2636ab4bcb34cf1e1e54db9933018a805b366727;hb=HEAD
Solution 3:
You can follow the answer provided by Richard in this link Rewriting symbols in static iOS libraries. This is more of a hack but using a hex editor you can rewrite the symbols if their length is kept the same. If you have more symbols and its a big library, you can consider using https://sourceforge.net/projects/bbe-/ and nm to write a script.
All of this is a considerable effort but apparently there is no shortcut.
Create a sample web application using the Web UI (web_ui) library, e.g., mylib
open mylib.dart, make it a library:
library mylib;
import 'dart:html';
import 'package:web_ui/web_ui.dart';
part 'xclickcounter.dart';
...
open xclickcounter.dart, remove imports and insert:
part of mylib;
web/out/mylib.dart and web/out/xclickcounter.dart get messed up:
The included part ''xclickcounter.dart'' must have a part-of directive
Classes can only mixin other classes
Mixin can only be applied to class
... more errors follow
What am I doing wrong? Please help :(
Edit: if I don't edit generated sample code, wdc will generate code that falls into separate libraries:
web/out/xclickcounter.dart => x_click_counter
web/out/mylib.dart => mylib_html
Does it mean that if we use web_ui we should not create our own libraries and wdc will do this for us automatically?
Update: if I don't use any library name, similar to what generated sample code does, and only rely on the library names generated by xdc in web/out/... files, I still run into trouble when importing my two components into a 3rd file. Dart Editor will produce the following warning:
The imported libraries 'compa.dart' and 'compb.dart'
should not have the same name
The workaround is to name your libraries based on what xdc produces in web/out/... files, that is:
compa.dart => x-comp-a
compb.dart => x-comp-b
After explicitly placing components into libraries like these the Dart Editor warning disappears.
I've had a major annoyance with the C++ Builder IDE for some time now. When I code I always use a standard layout for the code files. I have a standard header that I use, including, ie. the License of the file, filename, date, etc.
But I haven't been able to find anywhere to insert this, so that when I - for instance - create a new unit, get this header inserted automatically. Of course I can just paste it in, every time, but it gets a bit irritating to use time doing this.
So my question is - is it possible to create a file template for default C++ files or modify the existing ones so that they always start with my predefined layout. My fear is that just as with most other things in the C++ Builder IDE, this is hardcoded into it.
Currently creating a new unit creates a .cpp file with:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
and a corresponding header file with:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#endif
This is what I wish to alter to my own defined layout.
I'm using Codegear C++ Builder 2007.
See "Adding Items to the Object Repository" in the help file.
Basically,
1. Create the unit file(s) as you wish
2. Go to Project -> Add to Repository
3. Add information.
4. It will be available from the File -> New... area
There are also ways to share and edit repository items. The default distribution items are not quite as flexible, but creating your own should do just what you need.
For the defaults, see the answers to the question on reducing the "uses" clause boilerplate also located on stack overflow. This would require the same changes.